This code provides a sand box where we can watch a set of orthonormal vectors, ON, circulate about a Regge curvature bone in 4D. 4 four dimensional simplexes share a 2D simplex (triangle) which is our test bone. We can meddle with the embedding and even override the metric provided by the embedding.

I do not plan for this page to describe all of the technology that goes into this but this page gives pointers to all of the OCaml code and commentary on most of that. This page is a higher level index into these ideas.

There are 7 numbered vertices in this complex. For obscure reasons the vertices of the shared bone are numbered 0, 1 and 6. For a particular zone (4-simplex) its vertices are those of bone and two others. The numbers of the vertices of a particular zone are given in the array top (for topology). To get a running start at a metric for our complex, we embed it in flat 4D Euclidean space. We do this by assigning Cartesian coordinates to each of the 7 vertices. That information is provided by array coo. Since each zone uses its own coordinate system, indeed barycentric system, the intermediate reports of the progress of ON would be hard to interpret except that the vertices are embedded in flat 4D space to make these bcc coordinates nearly match the coordinates of the embedding space. This greatly aids debugging. When we move the vertices around in 4D however, these reports become obscure.

We create ON by the Gram-Schmidt method, causing the first two vectors to lie in the plane of the bone. Recall that we are building an orthogonal basis set but expressing them in an oblique coordinate system. This accounts for the parameter ip (inner product) to the Gram_Schmidt routine which is all Gram and Schmidt need to do their stuff. When ON arrives back in the zone where it started we do a transformation that results in the rotation caused by the loop, to be expressed and reported in the orthonormal coordinates, ON.

The general vector carrying logic has no access to the coordinates of the flat embedding space and so if we move those vertices in flat space, the measured curvature should remain zero; ON should return as the identity matrix. I hate to admit how many bugs I found making the measured curvature zero for an embedded complex. Now moving the embedding coordinates a little introduces no errors beyond rounding.

Meddling with the Metric

Here I take, rather as an axiom, that the distance between vertices is the ultimate input to our geometry, along with the topology, of course. Furthermore that these distances can be specified independently. I generally conform to the triangle inequality but things do not go badly wrong when that is flouted.

Actually the distance squared is the input and this results in no extra square roots in the program. I have a hunch that even those few will disappear when I improve the code. Specifying the distance2 has the additional advantage that a Minkowski metric may be specified by providing negative inputs.

The meddler can modify a list of specific point pairs and specify a floating point value that overrides the distance provided by the embedding. A report is made each time a substitution is made, giving the normal and overriding value. The first argument to exc in exc [([1; 2], 2.1)] pyt [i; j] is an example of a list of one override. There we say that the distance2 between vertices 1 and 2 is 2.1 whereas the embedding has it as 2.0 . Curiously this does change the curvature. Most such meddling does. Moving some vertices along with this fudge causes curvature that leaves the bone elements of ON unchanged.

We expand distance between vertices 2 and three for this increases the dihedral angle, at the bone, of zone 0. The text [([2; 3], 2.3)] does this.

[|[|1.; 0.;    0.;                0.|];
  [|0.; 1.;    0.;                0.|];
  [|0.; 0.; 0.98868599666425927; -0.15|];
  [|0.; 0.; 0.15; 0.988685996664259381|]|]
is reported which is indeed a simple rotation leaving the bone components unchanged. Shrinking the distance from 0 to 2 thus: [([2; 3], 2.3); ([0; 2], 1.8)] yields
[|[|1.; 0.; 0.;                    0.|];
  [|0.; 1.; 0.;                    0.|];
  [|0.; 0.; 0.988571053224161389; -0.150755672288881731|];
  [|0.; 0.; 0.150755672288881704;  0.988571053224161056|]|]

(define (ip a b) (if (null? a) 0 (+ (* (car a)(car b)) (ip (cdr a)(cdr b)))))