Compiled
This module contains subroutines that are written in Fortran90 and compiled during the installation of DISSTANS. They provide a significant speed boost compared to pure-Python implementations.
selectpair
selectpair
is the key function to calculate the MIDAS velocity estimates,
described in detail in [blewitt16]. It selects pairs of timestamps for a
one-year period (within a specified tolerance, and not crossing the specified
step times), but relaxes that assumption if no match can be found. Since there
is a lot of iteration, the (slightly modified for NumPy) Fortran code provided
by the author is included here for speed.
t is the array of timestamps in decimal years,
tstep is an array of step epochs in decimal years (with an additional, unused element necessarily added),
tolerance specifies how exactly the one-year period should be matched when searching for pairs,
n is the number of pairs found, and
ip is two-row NumPy array, where the first n columns contain the indices of the pairs to use in the MIDAS calculation.
- disstans.compiled.selectpair()
n,ip = selectpair(t,tstep,tol,[m,nstep])
Wrapper for
selectpair
.- Parameters
t (input rank-1 array('f') with bounds (m)) –
tstep (input rank-1 array('f') with bounds (1 + nstep)) –
tol (input float) –
m (input int, optional) – Default: shape(t, 0)
nstep (input int, optional) – Default: -1 + shape(tstep, 0)
- Returns
n (int)
ip (rank-2 array(‘i’) with bounds (2,19999))
Source Code
! file compiled.f90
! contains subroutines that speed up some tasks if they are precompiled
! This subroutine is taken from midas.f, downloaded from
! http://geodesy.unr.edu/MIDAS_release.tar on 2021-09-13,
! converted to F90, slightly modified to work better
! with Python/NumPy, and with hardcoded maxn.
! License of the original file:
! Author: Geoff Blewitt. Copyright (C) 2015.
SUBROUTINE selectpair(t, tstep, tol, m, nstep, n, ip)
!
! Given a time tag array t(m), select pairs ip(2,n)
!
! Moves forward in time: for each time tag, pair it with only
! one future time tag.
! First attempt to form a pair within tolerance tol of 1 year.
! If this fails, then find next unused partner.
! If this fails, cycle through all possible future partners again.
!
! MIDAS calls this twice -- firstly forward in time, and
! secondly backward in time with negative tags and data.
! This ensures a time symmetric solution.
! 2010-10-12: now allow for apriori list of step epochs
! - do not select pairs that span or include the step epoch
IMPLICIT NONE
! constant
INTEGER, PARAMETER :: maxn = 19999
! input
INTEGER, INTENT(IN) :: m, nstep
REAL, INTENT(IN) :: t(m), tstep(nstep+1), tol
! output
INTEGER, INTENT(OUT) :: n, ip(2, maxn)
! local
INTEGER :: i, j, k, i2, istep
REAL :: dt, fdt
k = 0
n = 0
istep = 1
DO i = 1, m
IF (n >= maxn) EXIT
IF (t(i) > (t(m) + tol - 1.0)) EXIT
! scroll through steps until next step time is later than epoch 1
DO
IF (istep > nstep) EXIT
IF (t(i) < tstep(istep) + tol) EXIT
istep = istep + 1
ENDDO
IF (istep <= nstep) THEN
IF (t(i) > (tstep(istep) + tol - 1.0)) CYCLE
ENDIF
DO j = i + 1, m
IF (k < j) k = j
IF (istep <= nstep) THEN
IF (t(j) > (tstep(istep) - tol)) EXIT
ENDIF
dt = t(j) - t(i)
! time difference from 1 year
fdt = (dt - 1.0)
! keep searching IF pair less than one year
IF (fdt < -tol) CYCLE
! try to find a matching pair within tolerance of 1 year
IF (fdt < tol) THEN
i2 = j
ELSE
! otherwise, if greater than 1 year, cycle through remaining data
i2 = k
dt = t(i2) - t(i)
IF (istep <= nstep) THEN
IF (t(i2) > (tstep(istep) - tol)) THEN
k = 0
CYCLE
ENDIF
ENDIF
IF (k == m) k = 0
k = k + 1
ENDIF
! data pair has been found
n = n + 1
ip(1, n) = i
ip(2, n) = i2
EXIT
ENDDO
ENDDO
END SUBROUTINE selectpair