Home > utilities > grid_vert_interp.m

grid_vert_interp

PURPOSE ^

Child function to interpolate a given 3D array (x by y by sigma) values

SYNOPSIS ^

function dataz = grid_vert_interp(Mobj, lon, lat, data, depth, mask, varargin)

DESCRIPTION ^

 Child function to interpolate a given 3D array (x by y by sigma) values
 to the unstructured grid vertical layers.

 function grid_vert_interp(Mobj, lon, lat, data, depth, mask)

 DESCRIPTION:
    Interpolate the regularly gridded data described by lon, lat, data
    (whose size should be x by y for the lon and lat arrays, and x by y by
    z for the data array) to the unstructured grid vertical layers defined
    in Mobj.siglayz. The depths in depth are used to make sure the profile
    is interpolated the right way up. The closest unstructured grid node
    is used for the vertical interpolation of each regularly gridded node.

 INPUT:
   Mobj        = MATLAB mesh structure which must contain:
                   - Mobj.have_lonlat - boolean for spherical coordinate
                   fields (Mobj.lon, Mobj.lat) presence (true = yes).
                   - Mobj.siglayz - sigma layer depths for all model
                   nodes.
   lon, lat    = Rectangular arrays of longitude and latitude (see
   meshgrid).
   data, depth = x by y by z (where z is vertical layers) grids of the
   data and water depths to be interpolated onto the vertical grid defined
   by Mobj.siglayz.
   mask        = logical array of positions outside the regularly gridded
   domain (e.g. if the regular data contains NaNs or other undefined
   values, create a logical array of those positions so they can be
   omitted quickly).
   'extrapolate' [optional] = keyword-argument pair in which the argument
   specifies the coordinates to use for the extrapolation (e.g.
   'extrapolate', [Mobj.lonc, Mobj.latc] to extrapolate onto the element
   centres). Defaults to the element nodes (i.e. [Mobj.lon, Mobj.lat]).

 OUTPUT:
   x by y by z array of vertically interpolated values at each regular
   grid location.

 EXAMPLE USAGE
   Basic usage:
       grid_vert_interp(Mobj, lon, lat, data, depth, mask)

   Extrapolate using the element centres.
       grid_vert_interp(Mobj, lon, lat, data, depth, mask, ...
           'extrapolate', [Mobj.lonc, Mobj.latc])

 Author(s):
   Pierre Cazenave (Plymouth Marine Laboratory)

 Revision history
   2013-02-08 First version.
   2013-05-16 Add support for parallel for-loops (not mandatory, but
   enabled if the Parallel Computing Toolbox is available).
   2014-04-28 Add new argument to allow specifying different coordinates
   for the extrapolation. This allows us to interpolate data which belongs
   either to the element centres or element nodes (defaults to element
   nodes). This is only really important when the model grid falls outside
   the coverage of the supplied data and we're extrapolating data. Update
   the parallel pool code to use the new parpool function instead of
   matlabpool in anticipation of the latter's eventual removal from
   MATLAB. Also update the help.
   2014-06-12 Fix bug in interpolating in the vertical when HYCOM data has
   only a single depth bin.

==========================================================================

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function dataz = grid_vert_interp(Mobj, lon, lat, data, depth, mask, varargin)
0002 % Child function to interpolate a given 3D array (x by y by sigma) values
0003 % to the unstructured grid vertical layers.
0004 %
0005 % function grid_vert_interp(Mobj, lon, lat, data, depth, mask)
0006 %
0007 % DESCRIPTION:
0008 %    Interpolate the regularly gridded data described by lon, lat, data
0009 %    (whose size should be x by y for the lon and lat arrays, and x by y by
0010 %    z for the data array) to the unstructured grid vertical layers defined
0011 %    in Mobj.siglayz. The depths in depth are used to make sure the profile
0012 %    is interpolated the right way up. The closest unstructured grid node
0013 %    is used for the vertical interpolation of each regularly gridded node.
0014 %
0015 % INPUT:
0016 %   Mobj        = MATLAB mesh structure which must contain:
0017 %                   - Mobj.have_lonlat - boolean for spherical coordinate
0018 %                   fields (Mobj.lon, Mobj.lat) presence (true = yes).
0019 %                   - Mobj.siglayz - sigma layer depths for all model
0020 %                   nodes.
0021 %   lon, lat    = Rectangular arrays of longitude and latitude (see
0022 %   meshgrid).
0023 %   data, depth = x by y by z (where z is vertical layers) grids of the
0024 %   data and water depths to be interpolated onto the vertical grid defined
0025 %   by Mobj.siglayz.
0026 %   mask        = logical array of positions outside the regularly gridded
0027 %   domain (e.g. if the regular data contains NaNs or other undefined
0028 %   values, create a logical array of those positions so they can be
0029 %   omitted quickly).
0030 %   'extrapolate' [optional] = keyword-argument pair in which the argument
0031 %   specifies the coordinates to use for the extrapolation (e.g.
0032 %   'extrapolate', [Mobj.lonc, Mobj.latc] to extrapolate onto the element
0033 %   centres). Defaults to the element nodes (i.e. [Mobj.lon, Mobj.lat]).
0034 %
0035 % OUTPUT:
0036 %   x by y by z array of vertically interpolated values at each regular
0037 %   grid location.
0038 %
0039 % EXAMPLE USAGE
0040 %   Basic usage:
0041 %       grid_vert_interp(Mobj, lon, lat, data, depth, mask)
0042 %
0043 %   Extrapolate using the element centres.
0044 %       grid_vert_interp(Mobj, lon, lat, data, depth, mask, ...
0045 %           'extrapolate', [Mobj.lonc, Mobj.latc])
0046 %
0047 % Author(s):
0048 %   Pierre Cazenave (Plymouth Marine Laboratory)
0049 %
0050 % Revision history
0051 %   2013-02-08 First version.
0052 %   2013-05-16 Add support for parallel for-loops (not mandatory, but
0053 %   enabled if the Parallel Computing Toolbox is available).
0054 %   2014-04-28 Add new argument to allow specifying different coordinates
0055 %   for the extrapolation. This allows us to interpolate data which belongs
0056 %   either to the element centres or element nodes (defaults to element
0057 %   nodes). This is only really important when the model grid falls outside
0058 %   the coverage of the supplied data and we're extrapolating data. Update
0059 %   the parallel pool code to use the new parpool function instead of
0060 %   matlabpool in anticipation of the latter's eventual removal from
0061 %   MATLAB. Also update the help.
0062 %   2014-06-12 Fix bug in interpolating in the vertical when HYCOM data has
0063 %   only a single depth bin.
0064 %
0065 %==========================================================================
0066 
0067 subname = 'grid_vert_interp';
0068 
0069 global ftbverbose
0070 if ftbverbose
0071     fprintf('\n')
0072     fprintf(['begin : ' subname '\n'])
0073 end
0074 
0075 if ~isfield(Mobj, 'siglayz')
0076     error('Error: missing required sigma layer depth values for the unstructured grid.')
0077 end
0078 
0079 if ~Mobj.have_lonlat
0080     error('Need spherical coordinates')
0081 end
0082 
0083 if sum(size(lon) ~= size(data(:, :, 1))) ~= 0 || sum(size(lat) ~= size(data(:, :, 1))) ~= 0
0084     error('Size of the longitude or latitude arrays do not match the supplied data array')
0085 end
0086 
0087 % Extract the extrapolation coordinates. Default to nodes but use
0088 % whatever's given if we have the 'extrapolate' argument.
0089 ulon = Mobj.lon;
0090 ulat = Mobj.lat;
0091 for aa = 1:2:length(varargin)
0092     switch varargin{aa}
0093         case 'extrapolate'
0094             ulon = varargin{aa + 1}(:, 1);
0095             ulat = varargin{aa + 1}(:, 2);
0096     end
0097 end
0098 
0099 wasOpened = false;
0100 if license('test', 'Distrib_Computing_Toolbox')
0101     % We have the Parallel Computing Toolbox, so launch a bunch of workers.
0102     try
0103         % New version for MATLAB 2014a (I think) onwards.
0104         if isempty(gcp('nocreate'))
0105             pool = parpool('local');
0106             wasOpened = true;
0107         end
0108     catch
0109         % Version for pre-2014a MATLAB.
0110         if matlabpool('size') == 0
0111             % Force pool to be local in case we have remote pools available.
0112             matlabpool open local
0113             wasOpened = true;
0114         end
0115     end
0116 end
0117 
0118 [~, fz] = size(Mobj.siglayz);
0119 [nx, ny, ~, ~] = size(data);
0120 
0121 % Preallocate the output arrays
0122 dataz = nan(nx, ny, fz);
0123 
0124 if ftbverbose
0125     tic
0126 end
0127 
0128 parfor xi = 1:nx
0129     % Get all the y and z dimension data for the current x position
0130     % (temperature, salinity and depth).
0131     xdata = squeeze(data(xi, :, :));
0132     xdepth = squeeze(depth(xi, :, :));
0133     xmask = mask(xi, :);
0134 
0135     % Preallocate the arrays for the inner loop.
0136     ydata = nan(ny, fz);
0137     for yi = 1:ny
0138         if xmask(yi)
0139             continue
0140         end
0141 
0142         % Find the nearest sigma layer z values from the unstructured grid.
0143         [md, mi] = min(sqrt((ulon - lon(xi, yi)).^2 + (ulat - lat(xi, yi)).^2));
0144 
0145         % Skip data point if the closest FVCOM node is more than 10 minutes
0146         % away.
0147         if md > 10 / 60
0148 %             if ftbverbose
0149 %                 fprintf('%s : skipping %f, %f (more than 10 minutes from the nearest unstructured grid node),\n', subname, lon(yi, xi), lat(yi, xi))
0150 %             end
0151             continue
0152         else
0153             % Use the FVCOM node's sigma depths to interpolate this regular
0154             % grid position's temperature and salinity data.
0155 
0156             % Get the FVCOM depths closest to this regular grid position.
0157             try
0158                 tfz = Mobj.siglayz(mi, :);
0159             catch
0160                 tfz = Mobj.siglayzc(mi, :);
0161             end
0162             % Now get the regular grid depths at this node for all the
0163             % vertical layers and linearly interpolate through the water
0164             % column onto the FVCOM vertical profile.
0165             tpz = xdepth(yi, :);
0166 
0167             % Remove any NaN values in the vertical depths (as is the case
0168             % with the HYCOM data, and interpolate only the data we have
0169             % that are finite).
0170             nidx = isnan(tpz);
0171             % If we have only a single value, repeat it down the entire
0172             % water column, otherwise, interpolate linearly (with
0173             % extrapolation).
0174             if length(tpz(~nidx)) == 1
0175                 ydata(yi, :) = tpz(~nidx);
0176             else
0177                 ydata(yi, :) = interp1(tpz(~nidx), xdata(yi, ~nidx), tfz, 'linear', 'extrap');
0178             end
0179         end
0180     end
0181     dataz(xi, :, :) = ydata;
0182 end
0183 
0184 % Close the MATLAB pool if we opened it.
0185 if wasOpened
0186     try
0187         pool.delete
0188     catch
0189         matlabpool close
0190     end
0191 end
0192 
0193 if ftbverbose
0194     toc
0195 end
0196 
0197 if ftbverbose
0198     fprintf(['end   : ' subname '\n'])
0199 end

Generated on Wed 20-Feb-2019 16:06:01 by m2html © 2005