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.