Subversion Repositories lagranto.ecmwf

Rev

Blame | Last modification | View Log | Download | RSS feed

function out = get_index (vert,position,grid);

% General index calculation for data grid
% Usage:   out = int_index(vert,coords,grid)   
% Example: grid.xmin = -180;
%          grid.dx   =    1;
%          grid.nx   =  361;
%          grid.ymin =    0;
%          grid.dy   =    1;
%          grid.ny   =   91;
%          out get_index(inp.P.data,[ 500 45 78; 250 56.7 78.4],grid)   

% Get the position arrays
xpos = position(:,3)';
ypos = position(:,2)';
zpos = position(:,1)';

% Get the grid dimension 
nx = size(vert,3);
ny = size(vert,2);
nz = size(vert,1);

% Get the horiozontal grid indices
rindx = (xpos-grid.xmin)/grid.dx+1;
rindy = (ypos-grid.ymin)/grid.dy+1;

% Special treatment if the the <vert> field is two-dimensional
if ( nz == 1 )
   out = [ ones(size(rindy))', rindy', rindx' ];
   return;
end 
    
% Direction of the vertical axis (Pressure: descencding, Height: ascending)
dir = vert(2:nz,:,:) - vert(1:nz-1,:,:);
if ( mean(dir(:)) > 0 ) 
     zpos = -zpos;
     vert = -vert;
end

% Get the weights for the individual grid points
fracx = 1-rindx+floor(rindx);
fracy = 1-rindy+floor(rindy);

% Combine the indices i and j to a common index ij
vert1 = reshape(vert,nz,nx*ny);

% The position array and the vertical index is needed in the same format
zpos1 = kron(ones(nz,1),zpos);
zind1 = kron([1:nz]',ones(size(zpos)));
shif1 = (0:length(zpos)-1) * nz;

% Get the vertical indices at position 00
indx           = floor(rindx);
indy           = floor(rindy);
indxy          = indy+(indx-1)*ny;
isnok1         = (indx<1) | (indx>nx) | (indy<1) | (indy>ny);
indxy(isnok1)  = 1;  
vert           = vert1(:,indxy);
indz           = max((vert>=zpos1).*zind1);
isnok2         = (indz<1) | (indz>=nz);
indz(isnok2)   = 1;
indu           = indz     + shif1;
indo           = indz + 1 + shif1;
diff           = vert(indo)-vert(indu);
isnok3         = (diff==0);
diff(isnok3)   = 1;
rind00         = indz + (zpos-vert(indu)) ./ diff;
isnok4         = isnok1 | isnok2 | isnok3;
rind00(isnok4) = NaN;

% Get the vertical indices at positions 01, 10, 11 (if necessary)
if ( any(fracx ~= 1) | any(fracy ~=1) ) 
    
    indx           = floor(rindx+1);
    indy           = floor(rindy);
    indxy          = indy+(indx-1)*ny;
    isnok1         = (indx<1) | (indx>nx) | (indy<1) | (indy>ny);
    indxy(isnok1)  = 1;  
    vert           = vert1(:,indxy);
    indz           = max((vert>zpos1).*zind1);
    isnok2         = (indz<1) | (indz>=nz);
    indz(isnok2)   = 1;
    indu           = indz     + shif1;  
    indo           = indz + 1 + shif1;
    diff           = vert(indo)-vert(indu);
    isnok3         = (diff==0);
    diff(isnok3)   = 1;
    rind01         = indz + (zpos-vert(indu)) ./ diff;
    isnok4         = isnok1 | isnok2 | isnok3;
    rind01(isnok4) = NaN;

    indx           = floor(rindx);
    indy           = floor(rindy+1);
    indxy          = indy+(indx-1)*ny;
    isnok1         = (indx<1) | (indx>nx) | (indy<1) | (indy>ny);
    indxy(isnok1)  = 1;  
    vert           = vert1(:,indxy);
    indz           = max((vert>zpos1).*zind1);
    isnok2         = (indz<1) | (indz>=nz);
    indz(isnok2)   = 1;
    indu           = indz     + shif1;  
    indo           = indz + 1 + shif1;
    diff           = vert(indo)-vert(indu);
    isnok3         = (diff==0);
    diff(isnok3)   = 1;
    rind10         = indz + (zpos-vert(indu)) ./ diff;
    isnok4         = isnok1 | isnok2 | isnok3;
    rind10(isnok4) = NaN;

    indx           = floor(rindx+1);
    indy           = floor(rindy+1);
    indxy          = indy+(indx-1)*ny;
    isnok1         = (indx<1) | (indx>nx) | (indy<1) | (indy>ny);
    indxy(isnok1)  = 1;  
    vert           = vert1(:,indxy);
    indz           = max((vert>zpos1).*zind1);
    isnok2         = (indz<1) | (indz>=nz);
    indz(isnok2)   = 1;
    indu           = indz     + shif1;  
    indo           = indz + 1 + shif1;
    diff           = vert(indo)-vert(indu);
    isnok3         = (diff==0);
    diff(isnok3)   = 1;
    rind11         = indz + (zpos-vert(indu)) ./ diff;
    isnok4         = isnok1 | isnok2 | isnok3;
    rind11(isnok4) = NaN;

else

    rind01 = rind00;
    rind10 = rind00;
    rind11 = rind00;
    
end
    
% Vectorised interpolation
rindz = fracx     .* fracy     .* rind00 + ...
        (1-fracx) .* fracy     .* rind01 + ...
        fracx     .* (1-fracy) .* rind10 + ...
        (1-fracx) .* (1-fracy) .* rind11;
        
% Set the output of the function
nok = isnan(rindz') | isnan(rindy') | isnan(rindx');
out = [ rindz', rindy', rindx' ];