Geodetic-velocity covariance matrix (.gp2) file format

by Peter Bird, 2019.04.12

A (.gps) GPS-geodesy file gives horizontal-plane velocity components and measurement-uncertainty ellipses for the steady, secular interseismic velocity of each benchmark.
My .gps file format was detailed here.

If the full GPS-velocity covariance matrix for these horizontal velocity components is available, it is placed in a second associated (.gp2) file.
At present, the .gp2 format is used to share data between 4 of my programs: GPS_Covariance, NeoKinema, Delete_Cracked_Benchmarks, & GPS_Postprocessor.
All of these programs are in the “NeoKinema family” of tools for kinematic finite-element modeling of neotectonics.

Every .gp2 file must have an associated .gps file to define its benchmark ordering, and all benchmark locations!

A .gps file can be read, understood, and used in computations without its associated .gp2 file.  However, any .gp2 file without an associated .gps file is worthless!
To keep the file-association strong, it is good practice to use matching filenames, such as: SCEC_CGM_2019.gps and SCEC_CGM_2019.gp2 and always store this file-pair in the same folder.
However, the matching-name ideal might have to be compromised if one used GPS_Covariance to build multiple variant versions of the .gp2 file (all mating with the same .gps file).

 

A full GPS-velocity covariance matrix can be quite large.  For example, with 2000 benchmarks included, the matrix includes a total of 16,000,000 numbers.  If every number were stored using 4 bytes (which would be about the maximum possible efficiency), then the file-size would be in the neighborhood of  64 MB.

However, there are two opportunities for slightly more efficient storage:

1.     Any covariance matrix is symmetric, so it is only necessary to store its diagonal & upper-triangle entries (or, diagonal & lower-triangle entries).

2.     Many off-diagonal values may be exactly zero, and (by convention) these can be omitted from the file.

My .gp2 format takes advantage of both of these facts.  Therefore, any program that reads in a .gp2 file must:

1.     Zero all the elements of the (full, square) matrix before any elements are read (in case they are never read).

2.     Place any entries that are read into both symmetrical positions in the matrix.

(The reading program might then proceed to replace the full square matrix with a smaller upper-triangle version (for example), if desired.)

 

Any .gp2 file is in plain-ASCII text format, so it is portable across many different computer systems.
It is human-readable, but not very human-friendly!

Each element of the matrix that is listed gets one line in the file.
The order of elements (and lines) in the file is completely unimportant, because the indices of each matrix element are included.
The maximum number of lines in a .gp2 file is equal to the number of diagonal & upper-triangle elements of the matrix.
If there are B benchmarks in the associated .gps file, then this maximum .gp2 file-size is (2B2 + B) lines.
(However, the file may actually be shorter, when zero off-diagonal elements are omitted.)
The .gp2 format does NOT include any line-count header, NOR any special end-of-file marker.
The file “just ends” after all the non-zero diagonal & upper-triangle elements have been listed;
therefore, the reading program must be able to detect and handle an EOF condition during READ operations;
in the Fortran 90 language this reading is most conveniently handled by:

INTEGER :: B, i, iGP2_unit, ios, j
REAL*8 :: r
REAL*8, DIMENSION(:,:), ALLOCATABLE :: gp2_matrix

B = … ! complete the right-side of this line to define the number of benchmarks (obtainable from the .gps file)
ALLOCATE ( gp2_matrix(2 * B, 2 * B ) )
gp2_matrix = 0.0D0 ! whole matrix

iGP2_unit = ! whatever integer UNIT# is not in use

OPEN (UNIT = iGP2_unit, FILE = …, STATUS = “OLD”)
gp2_loop: DO
            READ (iGP2_unit, *, IOSTAT = ios) i, j, r
            IF (ios /= 0) THEN
                        CLOSE (iGP2_unit)
                        EXIT gp2_loop
            ELSE
                        gp2_matrix(i, j) = r
                        gp2_matrix(j, i) = r
            END IF
END DO gp2_loop

 

As implied by the sample Fortran 90 code above, the structure of each line of a .gp2 file is simple.  In terms of data types:
INTEGER  INTEGER  REAL
and in terms of a specific example of a typical first line:
     1      1   7.5724E-01
which could also have been written as:
1  1  0.75724

The first integer is the row-number in the covariance matrix; the second integer is the column-number.
The two row-numbers (and also the two column-numbers) associated with benchmark #k (as implicitly numbered by its order in the associated .gps table) are ((2 * k) – 1), and (2 * k).
The Eastward component of horizontal velocity is numbered before the Northward component of horizontal velocity.

The number of characters used for each of these 3 entries in each line is not important, and columns do not need to be aligned from one line of the file to the next.
The only requirement is that there must be at least one space between the numbers, to separate them.

The final real (floating-point) number is the element of the covariance matrix, in (mm/a)2 = (millimeter/year)2 units.
Note that, on the diagonal, wherever i == j, it is required to be positive.