`ds2`is the (n+1) by (n+1) array of squared edge lengths for the zone.`neigh`is the mutable array of n+1 neighbor ports (type`nAcc`).`id`is a thunk whose side effect is to print an identification of the zone each time it is invoked. Now called each time a ray enters a zone.

`ray`- Introduce geodesic
`curl`- Curvature query concerning shared bone.

“**zbcc**” is a documentation term referring to barycentric coordinates in a zone.
“**fbcc**” is a documentation term referring to barycentric coordinates in an n−1 facet, with basis including the natural normal.

`Zone.newz` computes the covariant, `gd`, and contravariant, `gu`, metric tensors and keeps those within the zone.
`gu` is the n+1 by n+1 matrix; each row and column sum to 0.
The contravariant metric tensor for choice of any other vertex as origin may be had by eliminating some row and column of `gu`.
`ufn` is the array of n+1 normals to the facets in zbcc.

Messages between neighboring zones use the numbering plan of their shared facet; the zones do not have access to the global numbering plan.
The numbering plan of a zone’s facet is like that of the zone except for eliding the number by which the zone knows the facet.
`Zone.newz` is of type
`float array array -> fray nAcc array -> (unit -> 'a) -> int -> fray nAcc`.

- The
`float array array`argument is metric for this zone consisting of the squared edge lengths of the zone. - The
`fray nAcc array`argument is an unfilled array of ports to this zone’s n+1 neighbors. - The
`(unit -> 'a)`argument is a thunk the zone code uses to identify itself if printing is occurring as a ray passes thru. - The
`int`argument informs the zone code which neighbor sent a message. - The return value,
`fray nAcc`is a port for this zone to which messages may be sent to this zone from neighbors.

Values established in the zone during morphogenesis:

`gd`: n×n-covariant metric tensor. ('d' in 'gd' for ‘down’ as in subscript)`gu`: (n+1)×(n+1)-contravariant metric tensor.`ufn`: natural normals to respective facets, in zbcc.`l2 v`: squared length of n-vector v.`pi a k`: convert (n−1)-facet bcc position from facet k to (n+1)-zone bcc position.`po z k`: convert (n+1)-zone bcc position, z, to (n−1)-facet bcc position for facet k.`cvf2z v fn`: convert contravariant vector from facet bcc to zone bcc.`cvz2f v fn`: convert contravariant vector from zone bcc to facet bcc with UN sign flip. (See note.)

The real contravariant metric tensor, g^{ij} = `gu.(i).(j)`.
Omitting row j and column j from `gu` yields the contravariant metric tensor as if vertex j were chosen as origin.

The arguments to rayIn are:

`fn : int`- The number of the facet thru which the ray enters.
`lam : float`- The current value of λ, the geodesic parameter. λ increases from zone to zone. Perhaps the ray will stop when it reaches zero.
`wh : float array`(facet bcc, (n−1))- Where on the facet the ray enters.
`vel : float array`(facet bcc, (n), contravariant)- Velocity of ray.

I find the two trivial routines `ex` and `com` confusing.
I have had more bugs in such logic than all of the linear algebra.

`let ex f n = if f>n then n else n+1`- When we have the number, n, of a vertex in the numbering plan of facet f, then
`ex f n`yields the number of the same vertex in the zone’s numbering plan. `let cmp f z = if f=z then raise Hit4; if f<z then f else f-1`- When we have a local vertex (or facet) number z in the zone numbering plan, and need the number for the same vertex in the numbering plan of facet f, then write
`cmp f z`.

In `curl` code `k` is the zone’s number for the vertex opposite to which the message will be relayed.
That number together with `fn` which identifies the neighbor who sent the message, constitute the two numbers that identify the shared bone.
Expression `(if fn < k then fn else fn-1)` computes the vertex number, in the facet’s NP, of the facet vertex opposite the bone.

type fray = float array * float array type 'a rayp = float -> fray -> 'a type curlp = int * float array array -> float array array type 'a nAcc = {ray : 'a Zone.rayp; curl : Zone.curlp}