Interpolate irregularly spaced data using Kriging. The subroutine generates an empirical semivariogram (anisotropy is assumed), fits the best model among spherical, exponential and gaussian.
References:
Matheron, G. (1965) Les variables régionalisées et leur estimation: Une application de la theorie des fonctions aléatoires aux sciences de la nature. Masson, Paris.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
type(ObservationalNetwork), | intent(in) | :: | sitedata | |||
integer(kind=short), | intent(in) | :: | anisotropy |
if = 1, anisotropy is considered |
||
integer(kind=short), | intent(in) | :: | nlags |
the number of discrete distances used for comparing data, if 0 it is set to default value |
||
real(kind=float), | intent(in) | :: | maxlag |
maximum distance to consider for semivariogram assessment (m), if 0 it is automatically computed |
||
integer(kind=short), | intent(in) | :: | neighbors |
number of neighbors to consider for interpolation |
||
integer(kind=short), | intent(in) | :: | varModel |
semivariogram model, autofit for atomatic selecting the best among spherical, exponential, and gaussian |
||
type(grid_real), | intent(inout), | optional | :: | grid |
interpolated grid |
|
type(grid_real), | intent(inout), | optional | :: | gridvar |
variance of interpolated grid |
|
type(Coordinate), | intent(in), | optional | :: | points(:) |
list of coordinates for prediction (alternative to regular grid) |
|
real(kind=float), | intent(inout), | optional, | DIMENSION (:) | :: | predictions | |
real(kind=float), | intent(inout), | optional, | DIMENSION (:) | :: | predictionsVar |
Type | Visibility | Attributes | Name | Initial | |||
---|---|---|---|---|---|---|---|
type(ObservationalNetwork), | public | :: | active_stations | ||||
integer(kind=short), | public | :: | count | ||||
real(kind=float), | public | :: | est | ||||
type(site), | public, | DIMENSION (:), ALLOCATABLE | :: | estdist | |||
integer(kind=short), | public | :: | i | ||||
integer(kind=short), | public | :: | j | ||||
integer(kind=short), | public | :: | nclosest |
number of closest points to include in interpolation |
|||
integer(kind=short), | public | :: | outmodel |
semivariogram model selected by varfit |
|||
type(site), | public | :: | prediction_point | ||||
real(kind=float), | public | :: | variance | ||||
real(kind=float), | public | :: | x | ||||
real(kind=float), | public | :: | y |
SUBROUTINE Krige & ! (sitedata, anisotropy, nlags, maxlag, neighbors, varModel, grid, gridvar, & points, predictions, predictionsVar) IMPLICIT NONE !Arguments with intent (in): TYPE (ObservationalNetwork), INTENT(IN) :: sitedata INTEGER (KIND = short), INTENT(IN) :: anisotropy !! if = 1, anisotropy is considered INTEGER (KIND = short), INTENT(IN) :: nlags !! the number of discrete distances used for comparing data, if 0 it is set to default value REAL (KIND = float), INTENT(IN) :: maxlag !! maximum distance to consider for semivariogram assessment (m), if 0 it is automatically computed INTEGER (KIND = short), INTENT(IN) :: neighbors !! number of neighbors to consider for interpolation INTEGER (KIND = short), INTENT(IN) :: varModel !!semivariogram model, autofit for atomatic selecting the best among spherical, exponential, and gaussian TYPE (Coordinate), OPTIONAL, INTENT(IN) :: points (:) !!list of coordinates for prediction (alternative to regular grid) !Arguments with intent(inout): TYPE (grid_real), OPTIONAL, INTENT (INOUT) :: grid !!interpolated grid TYPE (grid_real), OPTIONAL, INTENT (INOUT) :: gridvar !!variance of interpolated grid REAL ( KIND = float), OPTIONAL, DIMENSION (:), INTENT (INOUT) :: predictions !interpolated values on not regular spaced points REAL ( KIND = float), OPTIONAL, DIMENSION (:), INTENT (INOUT) :: predictionsVar !variance of interpolated values on not regular spaced points !Local declarations TYPE(ObservationalNetwork) :: active_stations INTEGER (KIND = short) :: count INTEGER (KIND = short) :: nclosest !!number of closest points to include in interpolation INTEGER (KIND = short) :: i,j TYPE (site) :: prediction_point REAL (KIND = float) :: x, y TYPE(site), DIMENSION (:), ALLOCATABLE :: estdist REAL (KIND = float) :: est !estimated value REAL (KIND = float) :: variance INTEGER (KIND = short) :: outmodel !!semivariogram model selected by varfit !---------------------------end of declarations-------------------------------- !first check optional input data IF (PRESENT (grid) .AND. PRESENT (points) ) THEN CALL Catch ('error', 'Kriging interpolation', & 'only grid or points should be set for interpolation, they are mutual exclusive' ) END IF !create a subset of active stations CALL ActualObservations (sitedata, count, active_stations) !compute pair distance CALL PairDistance ( active_stations ) !compute direction angle when anisotropy analysis is required IF ( anisotropy == 1 ) THEN CALL PairDirection (active_stations ) END IF !initialize Kriging CALL KrigingInitialize (anisotropy, nlags, maxlag, count, neighbors, nclosest) !generate empirical semivariogram CALL Semivariogram ( active_stations) !automatic fitting of empirical semivariogram to the best model CALL VarFit (varModel, outModel) !Interpolate IF (PRESENT (grid) .OR. PRESENT(points) ) THEN !populate distance matrix CALL DistMatrix (active_stations) !set coordinate reference system of prediction point IF (PRESENT (grid)) THEN prediction_point % xyz % system = grid % grid_mapping ELSE prediction_point % xyz % system = points(1) % system END IF !allocate estdist ALLOCATE ( estdist ( count ) ) !Loop through prediction locations IF (PRESENT (grid)) THEN !interpolate regular spaced points DO i = 1, grid % idim DO j = 1, grid % jdim IF ( grid % mat (i,j) /= grid % nodata) THEN !set prediction point CALL GetXY (i, j, grid, x, y) prediction_point % xyz % easting = x prediction_point % xyz % northing = y !Build Estimation distance Vector estdist CALL Separation (prediction_point, active_stations, estdist) !Sort estdist to find the nearest neighbors of estimation location, and return !the prediction h vector and h matrix. CALL Sorted (estdist, nclosest) !Calculate est covariance from semivariance model, using the estimate to data !distance vector CALL Covariance(controlpts%h,controlpts%theta,cvest(1:nclosest), sill = partialsill, range = range, varmodel = outModel) !Add extra element for lagrangian minimisation cvest (nclosest + 1 ) = 1. !If control points for this datum are the same as for the last, the next steps !can be skipped over: Since distances between the observations are unchanged !the observation covariace matrix and its inverse are also unchanged. IF (ANY(last .NE. controlpts%oid)) THEN !Calculate observation covariance matrix from specified semivariance model, !using the observation distance matrix (hobs) CALL Covariance2d(hobs%h, hobs%theta, cvobs(1:nclosest,1:nclosest), sill = partialsill, range = range, varmodel = outModel) !Add extra row and column for lagrangian minimisation cvobs ( nclosest + 1, : ) = 1. cvobs ( :, nclosest + 1 ) = 1. cvobs ( nclosest + 1, nclosest + 1 ) = 0. !Invert Observation covariance Matrix CALL Matinv ( cvobs, cvobs ) END IF !Produce estimate for location CALL Interpolate (cvobs, cvest, controlpts%value, est, variance, nclosest, sill = (partialsill + nugget) ) grid % mat (i,j) = est IF (PRESENT(gridvar)) THEN gridvar % mat (i,j) = variance END IF !store last set of control points last = controlpts % oid END IF END DO END DO ELSE !interpolate not regular spaced points DO i = 1, SIZE(predictions) prediction_point % xyz % easting = points(i) % easting prediction_point % xyz % northing = points(i) % northing !Build Estimation distance Vector estdist CALL Separation (prediction_point, active_stations, estdist) !Sort estdist to find the nearest neighbors of estimation location, and return !the prediction h vector and h matrix. CALL Sorted (estdist, nclosest) !Calculate est covariance from semivariance model, using the estimate to data !distance vector CALL Covariance(controlpts%h,controlpts%theta,cvest(1:nclosest), sill = partialsill, range = range, varmodel = outModel) !Add extra element for lagrangian minimisation cvest (nclosest + 1 ) = 1. !If control points for this datum are the same as for the last, the next steps !can be skipped over: Since distances between the observations are unchanged !the observation covariace matrix and its inverse are also unchanged. IF (ANY(last .NE. controlpts%oid)) THEN !Calculate observation covariance matrix from specified semivariance model, !using the observation distance matrix (hobs). CALL Covariance2d(hobs%h, hobs%theta, cvobs(1:nclosest,1:nclosest), sill = partialsill, range = range, varmodel = outModel) !Add extra row and column for lagrangian minimisation cvobs ( nclosest + 1, : ) = 1. cvobs ( :, nclosest + 1 ) = 1. cvobs ( nclosest + 1, nclosest + 1 ) = 0. !Invert Observation covariance Matrix CALL Matinv ( cvobs, cvobs ) END IF !Produce estimate for location !sill = nugget + partial sill = C0 + C1 CALL Interpolate (cvobs, cvest, controlpts%value, est, variance, nclosest, sill = (partialsill + nugget) ) predictions (i) = est IF (PRESENT (predictionsVar)) THEN predictionsVar (i) = variance END IF !store last set of control points last = controlpts%oid END DO END IF END IF !free memory DEALLOCATE ( active_stations % obs ) DEALLOCATE ( dist_pairs ) IF (ALLOCATED (dir_pairs) ) DEALLOCATE ( dir_pairs ) DEALLOCATE ( dir ) DEALLOCATE ( lagNumber ) DEALLOCATE ( dist ) DEALLOCATE ( empVariogram ) DEALLOCATE ( modVariogram) DEALLOCATE ( pairNumber ) IF (ALLOCATED (obsdist) ) DEALLOCATE ( obsdist ) DEALLOCATE ( weights ) DEALLOCATE ( hest ) DEALLOCATE ( cvest ) IF (ALLOCATED ( estdist) ) DEALLOCATE ( estdist ) DEALLOCATE ( controlpts ) DEALLOCATE ( hobs ) DEALLOCATE ( cvobs ) DEALLOCATE ( last ) RETURN END SUBROUTINE Krige