# doc-cache created by Octave 6.4.0
# name: cache
# type: cell
# rows: 3
# columns: 36
# name: <cell-element>
# type: sq_string
# elements: 1
# length: 12
fastmarching


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 1532
 -- Function File: U = fastmarching (U0, F)
 -- Function File: [U, G] = fastmarching (U0, G0, F)

     Solve the Eikonal equation using the Fast-Marching Method.  In
     particular, the equation

          | grad u | = f

     is solved on a multi-dimensional domain.  U0 and F must be
     multi-dimensional arrays of the same dimension and size, and the
     returned solution U will be also of this size.  F should be
     positive, and we assume the grid spacing is unity (or,
     equivalently, has been absorbed into f already).

     U0 defines the initial setting and the domain.  It should contain
     the initial distances for points that are used as initially alive
     points, be 'Inf' for points not part of the domain, and 'NA' at all
     other points.  The latter are considered as far-away at the
     beginning and their distances will be calculated.  F is ignored at
     all but the far-away points.

     If G0 is also given, it should contain function values on initially
     alive points that will be extended onto the domain along the
     "normal directions".  This means that

          grad g * grad u = 0

     will be fulfilled for the solution U of the Eikonal equation.  G
     will be 'NA' at points not in the domain or not reached by the fast
     marching.

     At return, U will contain the calculated distances.  'Inf' values
     will be retained, and it may still contain 'NA' at points to which
     no suitable path can be found.

     See also: ls_signed_distance, ls_solve_stationary.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 58
Solve the Eikonal equation using the Fast-Marching Method.



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 16
ls_absolute_geom


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 967
 -- Function File: GEOM = ls_absolute_geom (GEOM, XX, YY)

     Extend the geometry structure GEOM of 'ls_find_geometry' to include
     absolute coordinates.  In addition to 'ls_find_geometry', this
     function has access to absolute grid-point coordinates, and uses
     them to set the additional 'GEOM.ispts.coord' field to absolute
     coordinates.  The format is the same as the relative coordinates in
     'GEOM.ispts.incoord'.  Also, it adds the new entry 'nodes' to GEOM,
     with the following fields:

     'n'
          Total number of nodes.  This is the number of entries in PHI.

     'coord'
          'n' x 2 matrix containing the absolute coordinates of each
          node.  The nodes are numbered in the range 1-'n' in the
          internal ordering of Octave.

     Currently, only 2D is supported.  XX and YY should be the
     grid-point coordinates according to 'meshgrid' or 'ndgrid'.

     See also: ls_find_geometry, meshgrid, ndgrid.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 80
Extend the geometry structure GEOM of 'ls_find_geometry' to include
absolute ...



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 20
ls_animate_evolution


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 446
 -- Function File: ls_animate_evolution (PHI, F, H, TIMES, WAIT)

     Animate the evolution of a level-set geometry.  The evolution is
     calculated with 'ls_solve_stationary' and 'ls_extract_solution' for
     the given arguments, and the result plotted in the current figure
     for the times given in TIMES.  Between updating to the next "movie
     frame", sleep for WAIT seconds.

     See also: ls_solve_stationary, ls_extract_solution.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 46
Animate the evolution of a level-set geometry.



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 13
ls_build_mesh


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 3544
 -- Function File: [MESH, VMAP] = ls_build_mesh (GEOM, PHI, GLOB =
          false)

     Build a triangle mesh for the level-set geometry described by GEOM
     and by the level-set function PHI.  Note that GEOM must contain
     absolute coordinates as set by 'ls_absolute_geom'.

     If GLOB is set to 'true', then the mesh will contain the whole
     hold-all domain and not just the interior of the level-set
     geometry.  It will, however, be constructed such that the boundary
     of the level-set domain is resolved precisely, and such that the
     level-set domain can be described as a subset of the mesh
     triangles.

     The mesh points will be made up _both_ of grid nodes as well as
     intersection points.  While all intersection points will appear as
     mesh nodes, unless GLOB is set, only *inner* grid nodes will
     correspond to mesh points.  The points on the mesh are numbered
     differently to the points in GEOM, although the indices can be
     translated both ways using VMAP (see below).

     On the other hand, the boundary edges of the mesh match precisely
     the edges given in 'GEOM.bedges'.  They have the same indices in
     both data structures.

     The returned struct MESH follows the format of the 'msh' package,
     which means that it contains these fields:

     'p'
          2 x NP matrix which contains the x- and y-coordinates of the
          mesh points in its two rows.

     't'
          4 x NT matrix describing the mesh triangles.  The first three
          rows contain the indices of mesh points making up the
          triangle, and the fourth row contains the index of the
          geometrical surface this triangle belongs to.  It is always
          set to '1' for now.  The points are ordered
          *counter-clockwise* (in the coordinate-system interpretation
          of the grid).

     'e'
          7 x NE matrix describing the edges of the mesh.  They
          correspond precisely to 'GEOM.bedges'.  The rows of this
          matrix are:

          1-2
               Start- and end-point index.  They are ordered such that
               the level-set domain is *on the left* of the edge.

          3-4
               Always '0' for compatibility.

          5
               The gamma component index (as per 'GEOM.gamma') that
               contains this edge.  Will be in the range
               1-'GEOM.gamma.n'.

          6-7
               Geometrical surface index of the domain parts to the
               right and left.  They are set to '0' and '1' for now.

     The second output, VMAP, describes the mappings between geometrical
     node / intersection-point indices in GEOM and the indices of the
     mesh points used in MESH.  It is a struct with these fields:

     'grid'
          Maps the index of a node on the grid to the index of the
          corresponding mesh point.  The value is 'NA' if the mesh does
          not contain the point.

     'ispt'
          Maps the index of an intersection point (according to
          'GEOM.ispts') to the index of the corresponding mesh point.

     'mesh'
          Maps the index of a mesh point back to either the grid or
          intersection-point index.  A *positive* value means that the
          mesh point is on the grid and has the respective index, while
          a *negative* value means that it is an intersection point with
          index equal to the absolute value of the entry.

     See also: ls_find_geometry, ls_absolute_geom,
     msh2m_structured_mesh.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 80
Build a triangle mesh for the level-set geometry described by GEOM and
by the...



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 8
ls_check


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 682
 -- Function File: OK = ls_check (PHI, TYPE, WHERE)

     Check a geometric constraint for the level-set function PHI.

     TYPE specifies what the constraint should be, and WHERE should be a
     logical array of the same size as the grid (and thus PHI),
     specifying which grid points are part of the set that defines the
     constraint.  Possible values for TYPE:

     "inside"
          The domain should be inside the region marked as WHERE.

     "outside"
          The domain should not intersect the region marked as WHERE.

     "contain"
          The domain should always contain the region marked in WHERE.

     See also: ls_enforce, ls_enforce_speed, ls_inside.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 60
Check a geometric constraint for the level-set function PHI.



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 13
ls_complement


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 420
 -- Function File: PHI = ls_complement (PHI)

     Construct a level-set function for the complement of the set
     described by PHI.

     This operation preserves a signed distance function: If PHI is
     actually the signed distance function of the set, then also the
     return value will be the signed distance function of the set's
     complement.

     See also: ls_union, ls_intersect, ls_setdiff, ls_setxor.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 78
Construct a level-set function for the complement of the set described
by PHI.



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 11
ls_disjoint


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 247
 -- Function File: RES = ls_disjoint (PHI1, PHI2)
 -- Function File: RES = ls_disjoint (PHI, ...)

     Check if all the sets described by the given level-set functions
     are disjoint.

     See also: ls_inside, ls_equal, is_issubset, ls_check.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 78
Check if all the sets described by the given level-set functions are
disjoint.



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 15
ls_distance_fcn


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 731
 -- Function File: D = ls_distance_fcn (PHI, H = 1)

     Calculate the distance function of a set.  The domain is described
     by its level-set function, whose values on a rectangular grid with
     spacing H are given in the array PHI.

     In contrast to 'ls_signed_distance', which calculates the _signed_
     distance function, D will be set to zero on interior points.  This
     allows 'ls_distance_fcn' to be faster, as only exterior points are
     processed.

     It may be a good idea to use 'ls_normalise' on the level-set
     function before using this method, to prevent almost-zero values
     from underflowing due to the performed calculations.

     See also: fastmarching, ls_signed_distance, ls_normalise.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 41
Calculate the distance function of a set.



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 10
ls_enforce


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 726
 -- Function File: PHI = ls_enforce (PHI, TYPE, WHERE)

     Enforce a geometric constraint for the level-set function PHI.  It
     will be updated to satisfy the constraint.

     TYPE specifies what the constraint should be, and WHERE should be a
     logical array of the same size as the grid (and thus PHI),
     specifying which grid points are part of the set that defines the
     constraint.  Possible values for TYPE:

     "inside"
          The domain should be inside the region marked as WHERE.

     "outside"
          The domain should not intersect the region marked as WHERE.

     "contain"
          The domain should always contain the region marked in WHERE.

     See also: ls_check, ls_enforce_speed.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 62
Enforce a geometric constraint for the level-set function PHI.



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 16
ls_enforce_speed


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 858
 -- Function File: F = ls_enforce_speed (F, TYPE, WHERE)

     Enforce geometric constraints by changing the speed field F
     accordingly.  This change ensures that the constraint is not
     violated while evolving a level-set function with the new speed
     field.

     TYPE specifies what the constraint should be, and WHERE should be a
     logical array of the same size as the grid (and thus F), specifying
     which grid points are part of the set that defines the constraint.
     Possible values for TYPE:

     "inside"
          The domain should be inside the region marked as WHERE.

     "outside"
          The domain should not intersect the region marked as WHERE.

     "contain"
          The domain should always contain the region marked in WHERE.

     See also: ls_check, ls_enforce, ls_solve_stationary,
     ls_extract_solution.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 72
Enforce geometric constraints by changing the speed field F accordingly.



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 8
ls_equal


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 415
 -- Function File: RES = ls_equal (PHI1, PHI2)

     Check if the sets described by PHI1 and PHI2 are equal.  This
     compares the domains according to 'ls_inside', but does not
     interpret magnitudes of the values and thus it does not take into
     account where exactly the "approximate boundary" intersects
     _between_ grid points.

     See also: ls_inside, ls_issubset, ls_disjoint, ls_hausdorff_dist.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 55
Check if the sets described by PHI1 and PHI2 are equal.



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 19
ls_extract_solution


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 618
 -- Function File: PHI = ls_extract_solution (T, D, PHI0, F)

     Calculate a level-set function of an evolving geometry from the
     result of 'ls_solve_stationary'.  In particular, it is assumed that
     'D = ls_solve_stationary (PHI0, F, H)'.  PHI is set to a level-set
     function for the evolved geometry at time T.  The zero level-set of
     PHI will describe the same geometry as the solution of the
     level-set equation

          d/dt phi + f | grad phi | = 0,

     although PHI will not be the full solution to this equation.

     See also: ls_solve_stationary, ls_time_step, ls_animate_evolution.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 80
Calculate a level-set function of an evolving geometry from the result
of 'ls...



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 16
ls_find_geometry


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 8808
 -- Function File: GEOM = ls_find_geometry (PHI, H = 1, FRACTOL = 1e-3)

     Interpret the level-set function PHI and extract geometrical
     properties.  A rectangular grid with spacing H uniform in each
     dimension is assumed.  This function assumes the 2D situation.

     The function assumes that PHI does not contain values which are
     exact zeros.  It is a good idea to use 'ls_normalise' before
     calling 'ls_find_geometry'.  Intersection points with edges very
     close to a grid point may be pushed away from it, governed by
     FRACTOL.

     The following terms will be used to denote certain elements of the
     geometrical description returned by this function:

     "node"
          A point on the grid.  PHI is the value of the level-set
          function at each node.  They are numbered from 1 to L x M in
          the same way as the entries in the matrix PHI are numbered.

     "element"
          One rectangular cell of the grid.  Since we work in 2D, each
          element is made up of four nodes (which are the vertices of
          the rectangle).  If the grid has L x M nodes, then it contains
          (L - 1) x (M - 1) elements.

     "inner element"
          An element for which each node is inside the described domain.

     "outer element"
          An element for which each node is outside of the described
          domain.

     "boundary element"
          An element which has both inside and outside nodes.  These
          elements are intersected by the boundary of the domain and
          have intersection points on some of their edges.

          It can be the case that it has two intersection points (when
          one boundary edge intersects it) or four (if we have a "narrow
          pair").  The latter case is that of _two_ intersecting
          (parallel) boundary edges, which happens when diagonally
          opposing nodes of the element have the same sign of PHI.

          A narrow pair is ambiguous as to which intersection points
          should be connected together.  This function is implemented
          such that it considers the "narrow channel" between the
          parallel boundary edges to be *outside* of the domain.  In
          other words, at a narrow pair, the domain is considered to be
          disconnected instead of connected with a narrow channel.

     "intersection point"
          A point on the _edge_ of a boundary element where the boundary
          of the described domain (approximately) intersects the grid
          (i.  e., PHI has a zero).  It can be characterised by a pair
          of inside/outside nodes at each end of the edge it intersects
          and by the fraction of the side that lies inside the domain.

     "gamma"
          The boundary of the described domain.  I. e., the curve given
          by the zero level-set of PHI.  It may consist of several
          components, which are each a closed curve.

     "boundary edge"
          A single edge of the domain's boundary, which is a line
          connecting two intersection points and cutting through a
          boundary element.  It is ordered in such a way that the domain
          is on the left, if the grid is interpreted as coordinate
          system.  (On the right in matrix ordering.)

     The returned variable GEOM will be a struct with these fields:

     'dim'
          The dimension of the grid, equal to 'size (PHI)'.

     'elem'
          Itself a struct describing the elements of the grid.  It
          contains:

          'n'
               Number of elements on the grid.  Equal to (L - 1) x (M -
               1) if PHI is L x M.

          'nodelist'
               'n' x 4 matrix containing in its rows the indices of
               nodes making up each element.  According to the ordering
               in the matrix PHI, the nodes are stored in the order SE,
               SW, NW, NE. Interpreted in a (x, y) grid constructed via
               'meshgrid', the order is instead NE, NW, SW, SE matching
               the usual numbering of quadrants in the plane.  (This is
               the case because the y axis points down when numbering
               rows of a matrix, but up in the usual coordinate system.)

          'type'
               A vector giving the type of each element.  It is -1, 0
               and 1 for inner, boundary and outer elements,
               respectively.  (This convention mimics the sign of PHI
               somewhat.)

          'index'
               Itself a struct with the fields 'inner', 'bdry' and
               'outer', containing a list of indices for inner, boundary
               and outer elements.

               These equal the result of 'find (GEOM.elem.type == X)'
               with X being -1, 0 and 1.

     'bdryel'
          A struct with information about the boundary elements.  They
          have their own index here, which can be mapped to the global
          element index via 'GEOM.elem.index.bdry'.  Its fields are:

          'n'
               Number of boundary elements.

          'edges'
               'n' x 4 matrix, whose columns correspond to the four
               edges of the boundary elements.  For each edge where an
               intersection point lies, the respective matrix entry is
               set to the intersection point's index into 'GEOM.ispts'.
               If there is no intersection point, the value is 'NA'.

               The edges are ordered similarly to the order in
               'GEOM.elem.nodelist'.  In matrix interpretation, the
               edges are in the columns as S, W, N, E. Interpreted as a
               coordinate grid, the order is N, W, S, E.

     'ispts'
          Struct containing details about the intersection points with
          the fields:

          'n'
               Number of intersection points.

          'inout'
               'n' x 2 matrix containing the node indices of the inner
               and outer nodes neighbouring each intersection point (in
               this order).

          'frac'
               Fraction of the edge that is inside the domain
               (connecting the intersection point to the inner neighbour
               node).  This value is always in the range 0-1,
               independent of H.

          'incoord'
               Coordinates of the intersection points relative to the
               neighbouring inner nodes as a 'n' x 2 matrix.  This takes
               H into account.

          'onedge'
               'n' x 2 x 3 array that indicates on which edges of which
               boundary elements this intersection point occurs.  The
               first dimension is indexed by intersection point number,
               the second dimension numbers the (two) boundary elements
               each intersection point is part of, and the third
               dimension contains the tuple (boundary element index,
               edge index, boundary edge index) in the ranges
               1-'GEOM.bdryel.n', 1-4 and 1-'GEOM.bedges.n'.

               The occurances (second dimension) are ordered such that
               the first one is where the boundary edge "enters" the
               boundary element, while the second one is where it
               "leaves" a boundary element.

          'gammachain'
               'n' x 2 matrix that contains for each intersection point
               the next and previous intersection point indices when
               following gamma.  See also 'GEOM.gamma.ispts'.

     'gamma'
          Struct with information about the components of the domain's
          boundary.  It contains these fields:

          'n'
               Number of gamma components.

          'ispts'
               Cell-array with 'n' elements.  Each element is a list of
               indices of intersection points (i.  e., indices into
               'GEOM.ispts').  In the order given, they can be joined
               together to form a closed curve (when also the last one
               is connected back to the first).

     'bedges'
          Information about the boundary edges:

          'n'
               Number of boundary edges in total.

          'comp'
               A vector giving the gamma component this edge is part of.
               The components are in the range 1-'GEOM.gamma.n'.

          'ispts'
               'n' x 2 matrix containing the intersection point indices
               that make up each boundary edge.

     'internal'
          Data field with additional information for internal use, in
          particular in 'ls_build_mesh'.  The precise format may be
          subject to change and should not be used.

     See also: ls_absolute_geom, ls_normalise, ls_build_mesh, ls_inside.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 72
Interpret the level-set function PHI and extract geometrical properties.



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 11
ls_genbasic


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 1219
 -- Function File: PHI = ls_genbasic (XX, YY, SHAPE, ...)
 -- Function File: PHI = ls_genbasic (XX, ..., SHAPE, ...)
 -- Function File: PHI = ls_genbasic (..., "sphere", C, R)
 -- Function File: PHI = ls_genbasic (..., "box", A, B)
 -- Function File: PHI = ls_genbasic (..., "half", P, N)

     Construct the level-set function for a basic geometric shape.  The
     arguments XX and YY should be the coordinates where the level-set
     function should be evaluated.  For a case that is not 2D, the
     respective number of arguments must be given.

     SHAPE specifies what shape should be constructed, the arguments
     following are shape-dependent.  Possible shapes:

     "sphere"
          Construct a sphere or ellipsoid with centre C and radius R.
          Optionally, R can also be a vector giving the radii in each
          coordinate direction separately.

     "box"
          Construct a box spanned by the given two vertex coordinates.

     "half"
          Construct a half-space at one side of a hyperplane.  The plane
          is specified by some point P on it, and the normal vector N
          pointing _into_ the domain.

     See also: ls_union, ls_intersect, ls_setdiff, meshgrid, ndgrid.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 61
Construct the level-set function for a basic geometric shape.



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 12
ls_get_tests


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 246
 -- Function File: PHIS = ls_get_tests ()

     Return a couple of level-set functions for certain 2D cases in the
     cell-array PHIS.  They can be used in tests.

     Use 'demo ls_get_tests' to get an overview of the situations
     included.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 80
Return a couple of level-set functions for certain 2D cases in the
cell-array...



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 17
ls_hausdorff_dist


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 1051
 -- Function File: DH = ls_hausdorff_dist (PHI1, PHI2, H = 1)
 -- Function File: DH = ls_hausdorff_dist (SD1, SD2, "sd")

     Approximate the Hausdorff distance between two sets.  The sets are
     given by their level-set functions PHI1 and PHI2.  The Hausdorff
     distance is calculated as the maximum difference between their
     distance functions.  (Note that it is the ordinary distance
     function here, not the _signed_ distance function!)

     If we neglect possible approximation errors in the distance
     function, the result DH is guaranteed to be a lower bound of the
     exact Hausdorff distance.  It is within the real distance by,
     roughly, H.

     The second call form assumes that the level-set functions of the
     domains are actually already signed distance functions SD1 and SD2.
     In this case, the grid spacing H is not necessary.  Since there is
     no need to call 'ls_distance_fcn', the calculation can be performed
     faster in this case.

     See also: ls_equal, ls_distance_fcn, ls_signed_distance.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 52
Approximate the Hausdorff distance between two sets.



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 18
ls_init_narrowband


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 1483
 -- Function File: D = ls_init_narrowband (PHI, H = 1)

     Calculate the estimated distances of grid points in the "narrow
     band" to the zero level-set of PHI.  The points considered are
     those which have neighbours with different sign of PHI.  The
     calculated distances are returned in D, where values for points not
     in the narrow band are set to 'NA'.  If the optional argument H is
     given, it is used as the grid spacing instead of the default value
     of 1.

     The distances will be positive or negative depending on the sign of
     PHI.  This means that D gives the signed distance function of the
     level-set domain for narrow-band points.

     We assume a linear model for PHI, meaning that the approximate
     intersection points on grid edges are calculated using linear
     interpolation.  The distances at narrow-band points are calculated
     using the quadratic update equation of the Fast-Marching Method
     using these approximated intersection points.

     Note that this method does not take an arbitrary speed field into
     account.  It assumes a uniform speed of 1 everywhere.  For
     different speeds, the resulting distances must be scaled as
     required.

     It may be a good idea to use 'ls_normalise' on the level-set
     function before using this method, to prevent almost-zero values
     from underflowing due to the performed calculations.

     See also: ls_signed_distance, ls_nb_from_geom, ls_normalise.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 80
Calculate the estimated distances of grid points in the "narrow band" to
the ...



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 9
ls_inside


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 404
 -- Function File: WHERE = ls_inside (PHI)

     Return in a logical array which points are inside the domain
     described by the level-set function PHI.  These are the points
     where PHI is negative.  If the 'signbit' function is available (on
     newer versions of GNU Octave), also negative zeros are considered
     to be part of the domain.

     See also: ls_check, ls_issubset, ls_normalise.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 80
Return in a logical array which points are inside the domain described
by the...



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 12
ls_intersect


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 301
 -- Function File: PHI = ls_intersect (PHI1, PHI2)
 -- Function File: PHI = ls_intersect (PHI, ...)

     Calculate a level-set function for the intersection of the sets
     described by the argument level-set functions.

     See also: ls_complement, ls_union, ls_setdiff, ls_setxor,
     intersect.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 80
Calculate a level-set function for the intersection of the sets
described by ...



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 10
ls_isempty


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 126
 -- Function File: RES = ls_isempty (PHI)

     Check if the set described by PHI is the empty set.

     See also: ls_inside.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 51
Check if the set described by PHI is the empty set.



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 11
ls_issubset


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 171
 -- Function File: RES = ls_issubset (PHI1, PHI2)

     Check if the set described by PHI1 is a subset of PHI2.

     See also: ls_inside, ls_equal, ls_disjoint, ls_check.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 55
Check if the set described by PHI1 is a subset of PHI2.



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 15
ls_nb_from_geom


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 1274
 -- Function File: D = ls_nb_from_geom (GEOM, PHI)
 -- Function File: [D, G] = ls_nb_from_geom (GEOM, PHI, G0)

     Initialise the narrow-band values utilising information about the
     geometry.  GEOM should be the geometry according to
     'ls_find_geometry', and it must contain absolute coordinates as per
     'ls_absolute_geom' in addition.  Thus it is unnecessary to pass the
     grid spacing, as this information is already contained in the
     absolute coordinates.  This is an alternative routine to the
     standard 'ls_init_narrowband' for 2D situations.

     This function sets the distance at _each_ node of a boundary
     element to the shortest distance to any boundary edge according to
     the geometry information in GEOM.  In contrast to
     'ls_init_narrowband', this also initialises values on the "far
     diagonally away" point.  This makes the result more accurate.

     In the second form, G0 is expected to contain the values of some
     function defined on each boundary edge (ordered in the same way as
     'GEOM.bedges').  These function values will be extended onto
     narrow-band points as well, and returned in G.

     See also: ls_init_narrowband, ls_find_geometry, ls_absolute_geom,
     ls_solve_stationary, fastmarching.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 75
Initialise the narrow-band values utilising information about the
geometry.



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 12
ls_normalise


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 762
 -- Function File: PHI = ls_normalise (PHI, H = 1, ZEROTOL = 1e-3)

     Normalise the level-set function PHI.  This gets rid of values that
     are exactly zero, by ensuring that each entry of the changed
     level-set function has a magnitude of at least H * ZEROTOL.  The
     actual level-set geometry is not changed, except possibly the
     approximated intersections between the zero level-set and grid
     edges due to slight variations in the actual values of PHI.

     Exactly zero values are interpreted according to their sign bit if
     the 'signbit' function is available (on newer versions of GNU
     Octave).  If the function is not available, then zeros are assumed
     to be *not* part of the level-set domain.

     See also: ls_inside.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 37
Normalise the level-set function PHI.



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 10
ls_setdiff


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 210
 -- Function File: PHI = ls_setdiff (PHI1, PHI2)

     Calculate a level-set function for the set difference PHI1 minus
     PHI2.

     See also: ls_complement, ls_union, ls_intersect, ls_setxor,
     setdiff.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 70
Calculate a level-set function for the set difference PHI1 minus PHI2.



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 9
ls_setxor


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 361
 -- Function File: PHI = ls_setxor (PHI1, PHI2)

     Calculate a level-set function for the set "xor" of the two domains
     given via PHI1 and PHI2.  In other words, returned is a domain that
     contains all points that are in precisely _one_ of the sets but not
     in both.

     See also: ls_complement, ls_union, ls_intersect, ls_setdiff,
     setxor.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 80
Calculate a level-set function for the set "xor" of the two domains
given via...



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 18
ls_signed_distance


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 706
 -- Function File: D = ls_signed_distance (PHI, H = 1)

     Calculate the signed distance function of a set described by its
     level-set function.  The array PHI must contain the values of the
     level-set function on a rectangular grid with spacing H.

     The initial distances are approximated using 'ls_init_narrowband',
     and then 'fastmarching' is used to propagate them to all other
     points on the grid.

     It may be a good idea to use 'ls_normalise' on the level-set
     function before using this method, to prevent almost-zero values
     from underflowing due to the performed calculations.

     See also: fastmarching, ls_distance_fcn, ls_solve_stationary,
     ls_normalise.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 80
Calculate the signed distance function of a set described by its
level-set fu...



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 19
ls_solve_stationary


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 1632
 -- Function File: D = ls_solve_stationary (PHI, F, H = 1)
 -- Function File: D = ls_solve_stationary (PHI, F, H = 1, NB)

     Solve a generalised Eikonal equation with speeds of arbitrary
     signs.  The equation solved is

          f | grad d | = 1

     with d = 0 on the boundary.  The domain is described by the
     level-set function PHI on a rectangular grid.  F should contain the
     values of the speed field on the grid points.  H can be given as
     the grid spacing.  In the second form, where the optional NB is
     given, it is used to initialise the narrow band with a manual
     calculation.  By default, the result of 'ls_init_narrowband' is
     used.  Values which are not fixed by the narrow band should be set
     to 'NA'.

     Note that in comparison to 'fastmarching', the speed need not be
     positive.  It is the reciprocal of F in 'fastmarching'.

     This is a preparation step, and afterwards, the evolved geometry
     according to the level-set equation

          d/dt phi + f | grad phi | = 0

     can be extracted from D at arbitrary positive times using the
     supplemental function 'ls_extract_solution'.

     At points where F is exactly zero, the output will be set to 'NA'.
     This case is handled separately in 'ls_extract_solution'.  In the
     narrow band, the returned distances may actually be negative even
     for positive F and vice-versa.  This helps to avoid unnecessary
     errors introduced into the level-set function due to a finite
     grid-size when the time step is chosen small.

     See also: ls_extract_solution, ls_signed_distance, ls_nb_from_geom.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 68
Solve a generalised Eikonal equation with speeds of arbitrary signs.



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 12
ls_time_step


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 1207
 -- Function File: PHIT = ls_time_step (T, PHI0, F, H = 1)
 -- Function File: PHIT = ls_time_step (T, C, PHI0, F, H = 1)

     Evolve the level-set equation with time stepping.  Perform explicit
     time stepping on the equation

          d/dt phi + f | grad phi | = 0.

     The initial value is given by PHI0.  PHI0 and F must be of the same
     size.  If H is present, it sets the spatial grid size.  The time
     stepping uses 'upwind_gradient_norm' for the evaluation of the
     gradient norm at each step.

     T is the time (or vector of times) at which the solution should be
     returned.  If more than one time is given, the result PHIT will be
     a cell array of the evolved level-set functions at each of the
     requested time points.  If T is a scalar, PHIT is returned as array
     of the same size of PHI0.

     The time step is chosen to satisfy the Courant-Friedrichs-Lewy
     condition

          dt = c h / (Fm * n).

     Here, Fm is the maximum absolute value in F, and n is the number of
     space dimensions.  The desired ratio c is by default one, but can
     be passed explicitly with the second usage form.

     See also: ls_extract_solution, upwind_gradient_norm.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 49
Evolve the level-set equation with time stepping.



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 8
ls_union


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 286
 -- Function File: PHI = ls_union (PHI1, PHI2)
 -- Function File: PHI = ls_union (PHI, ...)

     Calculate a level-set function for the union of the sets described
     by the argument level-set functions.

     See also: ls_complement, ls_intersect, ls_setdiff, ls_setxor,
     union.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 80
Calculate a level-set function for the union of the sets described by
the arg...



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 18
so_explore_descent


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 2155
 -- Function File: so_explore_descent (FILE, INIT)

     Interactively explore a descent file saved by 'so_save_descent'.
     This opens a shell where the user can navigate through the replay.

     The arguments are the same as for 'so_replay_descent'.  In order to
     allow backwards navigation, FILE must either be a file name or a
     file descriptor that allows seeking.

     On the initial call, the 'initialised' handler is called.  Then,
     'before_step', 'direction' and 'after_step' will be called for the
     currently active data at each navigation of the user.  Note that
     the descent steps on which they are called may be out-of-order and
     may skip intermediate iterations.  The 'finished' handler will be
     called with the data that is active when the user closes the
     interactive session.

     Note that 'DATA.log.steps' and 'DATA.log.costs' will always contain
     _all_ steps and costs that have been loaded during the replay so
     far, which may not correspond to the currently active step.  These
     fields will be present in all calls to handlers except
     'initialised', not just for the call to 'finished'.

     In addition to the default handlers in 'handler' of the DATA
     struct, also extra handlers can be defined in 'DATA.onFirst'.  They
     will be called _in order_ and _on each_ iteration when it is first
     loaded from the descent log.  The 'finished' handler will be called
     on the last iteration data that has been loaded before the session
     is terminated.  This may not be the active data at that point in
     time, if the user has navigated backwards.  The 'onFirst' handlers
     (if present) will be called before the corresponding 'handler'
     functions.

     No on-the-fly computation of extra steps (as it is done by
     'so_replay_descent' when not enough steps are saved in the log) is
     supported by this routine.  Instead, it is simply not possible to
     step beyond EOF of the log file.

     This routine requires 'fload' from the 'parallel' package to be
     available.

     See also: so_replay_descent, so_run_descent, so_save_descent,
     fload.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 64
Interactively explore a descent file saved by 'so_save_descent'.



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 14
so_init_params


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 719
 -- Function File: P = so_init_params (VERBOSE, NPROC = 1)

     Initialise the parameter structure for the shape optimisation
     routines.  Choose default parameters, and set whether or not
     "verbose" log chatter should be printed.

     NPROC specifies the number of processes to use for some steps that
     can be done in parallel (like the line search with
     'so_step_armijo').  If this number is larger than one, the function
     'pararrayfun' from the 'parallel' package must be available.

     The result of this function call can be used as a basis for
     defining 'DATA.p'.  Values can be overwritten after the call where
     desired.

     See also: so_run_descent, so_step_armijo, pararrayfun.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 71
Initialise the parameter structure for the shape optimisation routines.



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 17
so_replay_descent


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 1747
 -- Function File: [S, LOG] = so_replay_descent (FILE, INIT)
 -- Function File: [S, LOG] = so_replay_descent (FILE, INIT, NSTEPS)

     Replay a descent file saved by 'so_save_descent'.  FILE should be
     either an already open file descriptor or a file name to be opened
     in "rb" mode.

     INIT must be a function that can be called with the "header" saved
     in the descent log.  It should return the DATA structure to use for
     the descent run.  The handlers defined in 'DATA.handler' will be
     called in the same way as they would by 'so_run_descent'.  Also
     similar log chatter will be printed if 'DATA.p.verbose' is 'true'.

     If the state structs were compressed when saving with
     'so_save_descent', a routine should be provided to "uncompress"
     them as necessary.  This function should be defined in
     'DATA.compress.load.state' and should return the uncompressed state
     struct when called with the arguments '(S, DATA)' where S is the
     compressed struct.

     If NSTEPS is not given, the file is read until EOF is encountered.
     If NSTEPS is present, the descent will be run until either this
     number is reached or 'DATA.cb.check_stop' returns true.  If the
     descent log does not contain enough data for this condition to be
     fulfilled, more steps will be performed according to
     'so_run_descent'.  In this case, the callbacks in 'DATA.cb' must be
     set in the same way as for 'so_run_descent'.

     Returned are the final state and the produced log structure, in the
     same way as by 'so_run_descent'.

     This routine requires 'fload' from the 'parallel' package to be
     available.

     See also: so_explore_descent, so_run_descent, so_save_descent,
     fload.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 49
Replay a descent file saved by 'so_save_descent'.



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 14
so_run_descent


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 7823
 -- Function File: [S, LOG] = so_run_descent (NSTEPS, PHI0, DATA)

     Run a descent method for shape optimisation.  This routine is quite
     general, since the actual "descent direction" used must be computed
     by a callback (see below).  It is thus not just for steepest
     descent.  At each step, a line search according to 'so_step_armijo'
     is employed.

     NSTEPS defines the maximal number of descent steps to take.  After
     this number, the method returns no matter whether or not the
     stopping criterion is fulfilled.  PHI0 is the initial geometry to
     use.  Returned are the final state and the descent log structs (see
     below).

     DATA contains all the information about the actual problem.  This
     includes various parameters that influence the behaviour of this
     and other routines.  Furthermore, also some callback functions must
     be defined to evaluate the cost functional and to determine the
     next descent direction.  This struct is also updated with the
     current state at each optimisation step and passed to the callback
     functions.

     Most content of DATA is read-only, with 'DATA.s' and 'DATA.log'
     being the only exceptions.  They are updated accordingly from the
     results of the callback functions and the optimisation descent.
     These two structs will be created and filled in by
     'so_run_descent'.  'DATA.log' is preserved if it is already
     present.  'DATA.s' will always be overwritten with the initial
     result of the 'update_state' callback.

     The struct 'DATA.p' contains parameters.  They can contain
     problem-dependent parameters that are handled by the callback
     routines as well as parameters for the line search with
     'so_step_armijo'.  This routine is influenced by the following
     parameters directly:

     'verbose'
          Whether or not log chatter should be printed.

     'descent.initialStep'
          Initial trial step length for the line search in the first
          iteration.

     'descent.projectSpeed'
          If set, project the speed field (in L2, discontinuously) to
          enforce geometric constraints (see below).  If not set or
          missing, the geometry is projected instead.

     The routine 'so_init_params' can be used to initialise the
     parameter structure with some defaults.

     Information about the used grid and grid-dependent data should be
     in 'DATA.g'.  Generally defined are the following fields:

     'h'
          The grid spacing.

     'constraints'
          Optional, can be used to specify the hold-all domain and
          contained regions as shape constraints.  If specified, the
          shape or the speed field will be "projected" (depending on
          'DATA.p.descent.projectSpeed') to satisfy the constraints.
          The callback computing the descent direction is also a good
          place to take the constraints into account in a
          problem-specific way.

          The following fields (as logical arrays with the grid size)
          can be used to specify the constraints:

          'holdall'
               The hold-all domain.  The current shape must always be
               part of it.  By excluding interior parts of the grid,
               forbidden regions can be defined.

          'contained'
               A part of the hold-all domain that should always be part
               of the shape.

     The specific problem is handled by _callback routines_ to compute
     the cost and find descent directions.  They must be set in
     'DATA.cb', with these interfaces:

     'S = update_state (PHI, DATA)'
          Compute the state (see below) for the geometry described by
          PHI.  The main work done by this callback is evaluating the
          cost functional.  It does not need to update 'S.phi' to PHI,
          this will be done automatically after the call.

     '[F, DJ] = get_direction (DATA)'
          Compute the speed field F and its associated directional shape
          derivative DJ to be used as the next descent direction.  The
          current cost and geometry can be extracted from 'DATA.s'.

     'EXIT = check_stop (DATA)'
          Determine whether or not to stop the iteration.  Should return
          'true' if the state in DATA satisfies the problem-specific
          stopping criterion.  If not present, no stopping criterion is
          used and the iteration done for precisely NSTEPS iterations.

     'D = solve_stationary (F, DATA)'
          Solve the stationary Eikonal equation for the speed field.  If
          not present, 'ls_solve_stationary' is used.  It can be set
          explicitly to give a more appropriate routine.  For instance,
          'ls_nb_from_geom' could be used if geometry information is
          computed.

     Additional callback functions can be defined optionally in
     'DATA.handler'.  They can keep problem-specific logs of the
     descent, plot figures, print output or something else.  They should
     always return a (possibly) updated log struct, which will be
     updated in 'DATA.log' after the call.  This struct can also be used
     to persist information between calls to the handlers.  These
     handlers can be defined:

     'LOG = initialised (DATA)'
          Called before the iteration is started.  'DATA.s' contains the
          initial geometry and computed state data for it.

     'LOG = before_step (K, DATA)'
          Called when starting a new step, before any action for the
          step is taken.  K is the number of the iteration and 'DATA.s'
          contains the current state.

     'LOG = direction (K, F, DJ, DATA)'
          Called when the descent direction has been determined.  F and
          DJ are the results of 'DATA.cb.get_direction'.

     'LOG = after_step (K, T, S, DATA)'
          Called after a step has been found.  T is the step length
          found by the line search.  S is the state struct after the
          step has been taken.  The previous state can still be found in
          'DATA.s'.

     'LOG = finished (DATA)'
          Called after the descent run.  'DATA.log' is already filled in
          with the standard data (number of steps and costs at each
          step).

     Note that information about the speed field F is only passed to the
     'direction' handler and _not again_ to 'after_step'.  If it is
     required by the latter, it should be saved somehow in the log
     struct.  This way, the handlers really only receive new information
     and no redundant arguments.

     Finally, we come to the state struct 'DATA.s'.  It must contain at
     least the fields below, but can also contain problem-specific
     information that is, for instance, computed in the 'update_state'
     handler and reused for computing the descent direction.

     'phi'
          The level-set function of the current geometry.  This is
          automatically updated after the 'update_state' handler has
          been called.

     'cost'
          Value of the cost functional for the geometry in 'DATA.s.phi'.

     The log struct can contain mostly user-defined data, but
     'so_run_descent' will also fill in some data by itself:

     's0'
          The state struct corresponding to the initial geometry defined
          by PHI0.

     'steps'
          Total number of steps done.  This is useful if the stopping
          criterion was satisfied before NSTEPS iterations.

     'costs'
          Cost values for all steps.  This will be a vector of length
          'DATA.log.steps + 1', since it contains both the initial and
          the final cost value in addition to all intermediate ones.

     See also: so_init_params, so_save_descent, so_replay_descent,
     so_explore_descent, so_step_armijo.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 44
Run a descent method for shape optimisation.



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 15
so_save_descent


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 1589
 -- Function File: DATA = so_save_descent (FILE, HEADER, DATA)

     Update handlers to save the descent run to a file.  The existing
     handlers in DATA will be kept, but additional logic will be added
     to them that saves all data computed during the descent run to a
     file.  This file can then be used with 'so_replay_descent'.

     FILE can either be a file ID (integer) or file name (string).  In
     the latter case, the file will be created in "wb" mode and closed
     after the descent run.  HEADER should be some data (possibly a
     struct) that will be written as the "file header".  It can contain
     data that identifies the problem solved and all parameter values.
     It must be possible to reproduce a problem's DATA structure from
     this header when replaying the descent.

     The state struct can be optionally "compressed" before it is
     written, in case it contains excessive amounts of data that is not
     necessary for the replay (for instance, because it is cheap to
     re-compute).  If this feature should be used, a function must be
     defined that translates the state struct accordingly.  It should be
     stored in 'DATA.compress.save.state', and will be called with
     arguments '(S, DATA)'.  It should return the state struct in the
     form to save it.

     This routine requires 'fsave' from the 'parallel' package to be
     available.  Note that the files are not guaranteed to be
     interoperable between machines or package versions.

     See also: so_run_descent, so_replay_descent, so_explore_descent,
     fsave.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 50
Update handlers to save the descent run to a file.



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 14
so_step_armijo


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 2166
 -- Function File: [S, T] = so_step_armijo (T0, D, F, DJ, DATA)

     Perform a line search according to the Armijo rule.  A backtracking
     strategy is employed, such that the returned step length T
     satisfies

          J(t) <= J(0) + t * tau * dJ.

     T0 defines the initial step length (see below).  It can be set to
     some suitable constant or to the last successful step length.  D
     should be the result of 'ls_solve_stationary' for the current
     geometry, and F the matching speed field on the grid.  DJ must be
     the directional shape derivative of the cost functional in
     direction F.  This value must be negative.

     Data defining the problem, the current state and parameters should
     be passed in DATA.  See 'so_run_descent' for a description of this
     struct.

     Returned is the final state struct in S and the corresponding step
     length taken in T.

     The following parameters must be set in 'DATA.p.lineSearch' to
     determine how the Armijo line search is done:

     'relaxation'
          The parameter tau in the Armijo rule.

     'backtrack'
          Backtracking factor.  Should be less than one.

     'initial'
          Factor for increasing T0 to get the initial guess.  This
          should be larger than one in order to allow increasing of the
          step length when this is possible.

     'minStep'
          Minimum step length.  If backtracking goes below this value,
          use 'minStep' and disregard the condition.

     Furthermore, the following general parameters in 'DATA.p' also
     influence the behaviour of the line search:

     'verbose'
          Whether or not log chatter should be printed.

     'nProc'
          Number of parallel threads to use for the line search.  If
          this is larger than one, multiple trial steps are computed in
          parallel to speed up the computation.  For this to work,
          'pararrayfun' of the 'parallel' package must be available.

     The routine 'so_init_params' can be used to initialise the
     parameter structure with default values.

     See also: so_init_params, so_run_descent, ls_solve_stationary.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 51
Perform a line search according to the Armijo rule.



# name: <cell-element>
# type: sq_string
# elements: 1
# length: 20
upwind_gradient_norm


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 1220
 -- Function File: GNORM = upwind_gradient_norm (PHI, H = 1)
 -- Function File: GNORM = upwind_gradient_norm (PHI, F, H = 1)

     Approximate the gradient norm of PHI using an upwind scheme.  The
     scheme chosen is appropriate to propagate the level-set equation

          d/dt phi + f | grad phi | = 0

     in time.  If the argument F is given, its sign is used to find the
     correct upwind direction.  If it is not present, positive sign is
     assumed throughout the domain.  H gives the grid spacing to use for
     the difference approximation.

     PHI can be an array of arbitrary dimension, and GNORM is always of
     the same size as PHI.  If F is given, it must also be of the same
     size as PHI.

     The gradient is approximated with finite differences, either the
     forward or backward difference quotient.  The direction chosen at
     each grid point depends on the sign of f and the gradient of phi at
     that point.  The approximation used is from section 6.4 of

     J. A. Sethian: Level Set Methods and Fast Marching Methods, second
     edition, 1999.  Cambridge Monographs on Applied and Computational
     Mathematics, Cambridge University Press.

     See also: ls_time_step.


# name: <cell-element>
# type: sq_string
# elements: 1
# length: 60
Approximate the gradient norm of PHI using an upwind scheme.





