| 1 |
% [V,Cm,E,Vt,CC] = diagVOLU(FLAG,C1,C2,CLASS,LON,LAT,DPT,DV,[Ca(Z,Y,X),Cb(Z,Y,X),...]) |
| 2 |
% |
| 3 |
% DESCRIPTION: |
| 4 |
% Compute the volume of water for a particular CLASS of potential |
| 5 |
% temperature or density. |
| 6 |
% Also compute mean values of additional 3D fields (such as Ca, Cb ...) along |
| 7 |
% the CLASS of the analysed field. |
| 8 |
% |
| 9 |
% The volume is accounted as: |
| 10 |
% CLASS(i) <= FIELD < CLASS(i+1) |
| 11 |
% |
| 12 |
% INPUTS: |
| 13 |
% FLAG : Can either be: 0, 1 or 2 |
| 14 |
% 0: Compute volume of potential density classes |
| 15 |
% from C1=THETA and C2=SALT |
| 16 |
% 1: Compute volume of potential density classes |
| 17 |
% from C1=SIGMA_THETA |
| 18 |
% 2: Compute volume of temperature classes |
| 19 |
% from C1=THETA |
| 20 |
% C1,C2 : Depends on option FLAG: |
| 21 |
% - FLAG = 0 : |
| 22 |
% C1 : Temperature (^oC) |
| 23 |
% C2 : Salinity (PSU) |
| 24 |
% - FLAG = 1 : |
| 25 |
% C1 : Potential density (kg/m3) |
| 26 |
% C2 : Not used |
| 27 |
% - FLAG = 2 : |
| 28 |
% C1 : Temperature (^oC) |
| 29 |
% C2 : Not used |
| 30 |
% ClASS : Range to explore (eg: [20:.1:30] for potential density) |
| 31 |
% LON,LAT,DPT : axis (DPT < 0) |
| 32 |
% dV : Matrix of grid volume elements (m3) centered in (lon,lat,dpt) |
| 33 |
% Ca,Cb,...: Any additional 3D fields (unlimited) |
| 34 |
% |
| 35 |
% |
| 36 |
% OUTPUTS: |
| 37 |
% V : Volume of each CLASS (m3) |
| 38 |
% Cm : Mean value of the classified field (allow to check errors) |
| 39 |
% E : Each time a grid point is counted, a 1 is added to this 3D matrix |
| 40 |
% Allow to check double count of a point or unexplored areas |
| 41 |
% Vt : Is the total volume explored (Vt) |
| 42 |
% CC : Contains the mean value of additional fields Ca, Cb .... |
| 43 |
% |
| 44 |
% NOTES: |
| 45 |
% - Fields are on the format: C(DPT,LAT,LON) |
| 46 |
% - The potential density is computed with the equation of state routine from |
| 47 |
% the MITgcm called densjmd95.m |
| 48 |
% (see: http://mitgcm.org/cgi-bin/viewcvs.cgi/MITgcm_contrib/gmaze_pv/subfct/densjmd95.m) |
| 49 |
% - if dV is filled with NaN, dV is computed by the function |
| 50 |
% |
| 51 |
% |
| 52 |
% AUTHOR: |
| 53 |
% Guillaume Maze / MIT |
| 54 |
% |
| 55 |
% HISTORY: |
| 56 |
% - Created: 06/29/2007 |
| 57 |
% |
| 58 |
|
| 59 |
% |
| 60 |
|
| 61 |
function varargout = diagVOLU(FLAG,C1,C2,CLASS,LON,LAT,DPT,DV,varargin) |
| 62 |
|
| 63 |
|
| 64 |
% 0 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% PREPROC |
| 65 |
% Variables: |
| 66 |
ndpt = size(C1,1); |
| 67 |
nlat = size(C1,2); |
| 68 |
nlon = size(C1,3); |
| 69 |
CLASS = sort(CLASS(:)); |
| 70 |
[Z b c] = meshgrid(DPT,LON,LAT);clear b c, Z = permute(Z,[2 3 1]); |
| 71 |
|
| 72 |
% Determine fields from which we'll take class contours: |
| 73 |
switch FLAG |
| 74 |
|
| 75 |
case 0 % Need to compute SIGMA THETA |
| 76 |
THETA = C1; |
| 77 |
SALT = C2; |
| 78 |
ST = densjmd95(SALT,THETA,0.09998*9.81*abs(Z)) - 1000; |
| 79 |
CROP = ST; |
| 80 |
|
| 81 |
case 1 |
| 82 |
ST = C1; % Potential density |
| 83 |
CROP = ST; |
| 84 |
|
| 85 |
case 2 |
| 86 |
THETA = C1; % Potential temperature |
| 87 |
CROP = THETA; |
| 88 |
end |
| 89 |
|
| 90 |
% Volume elements: |
| 91 |
if length(find(isnan(DV)==1)) == ndpt*nlat*nlon |
| 92 |
if exist('subfct_getdV','file') |
| 93 |
DV = subfct_getdV(DPT,LAT,LON); |
| 94 |
else |
| 95 |
DV = local_getdV(DPT,LAT,LON); |
| 96 |
end |
| 97 |
end |
| 98 |
|
| 99 |
% Need to compute volume integral over these 3D fields |
| 100 |
nIN = nargin-8; |
| 101 |
if nIN >= 1 |
| 102 |
doEXTRA = 1; |
| 103 |
else |
| 104 |
doEXTRA = 0; |
| 105 |
end |
| 106 |
|
| 107 |
% 1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% VOLUME INTEGRATION |
| 108 |
explored = zeros(ndpt,nlat,nlon); |
| 109 |
% Volume integral: |
| 110 |
for iC = 1 : length(CLASS)-1 |
| 111 |
mask = zeros(ndpt,nlat,nlon); |
| 112 |
mask(find( (CLASS(iC) <= CROP) & (CROP < CLASS(iC+1)) )) = 1; |
| 113 |
explored = explored + mask; |
| 114 |
VOL(iC) = nansum(nansum(nansum(DV.*mask,1),2),3); |
| 115 |
|
| 116 |
if VOL(iC) ~= 0 |
| 117 |
CAR(iC) = nansum(nansum(nansum(CROP.*DV.*mask,1),2),3)./VOL(iC); |
| 118 |
if doEXTRA |
| 119 |
for ii = 1 : nIN |
| 120 |
C = varargin{ii}; |
| 121 |
CAREXTRA(ii,iC) = nansum(nansum(nansum(C.*DV.*mask,1),2),3)./VOL(iC); |
| 122 |
end %for ii |
| 123 |
end %if doEXTRA |
| 124 |
else |
| 125 |
CAR(iC) = NaN; |
| 126 |
if doEXTRA |
| 127 |
for ii = 1 : nIN |
| 128 |
CAREXTRA(ii,iC) = NaN; |
| 129 |
end %for ii |
| 130 |
end %if doEXTRA |
| 131 |
end |
| 132 |
end %for iC |
| 133 |
|
| 134 |
% In order to compute the total volume of the domain: |
| 135 |
CROP(find(isnan(CROP)==0)) = 1; |
| 136 |
CROP(find(isnan(CROP)==1)) = 0; |
| 137 |
Vt = nansum(nansum(nansum(DV.*CROP,1),2),3); |
| 138 |
|
| 139 |
% 2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% OUTPUTS |
| 140 |
switch nargout |
| 141 |
case 1 |
| 142 |
varargout(1) = {VOL}; |
| 143 |
case 2 |
| 144 |
varargout(1) = {VOL}; |
| 145 |
varargout(2) = {CAR}; |
| 146 |
case 3 |
| 147 |
varargout(1) = {VOL}; |
| 148 |
varargout(2) = {CAR}; |
| 149 |
varargout(3) = {explored}; |
| 150 |
case 4 |
| 151 |
varargout(1) = {VOL}; |
| 152 |
varargout(2) = {CAR}; |
| 153 |
varargout(3) = {explored}; |
| 154 |
varargout(4) = {Vt}; |
| 155 |
case 5 |
| 156 |
varargout(1) = {VOL}; |
| 157 |
varargout(2) = {CAR}; |
| 158 |
varargout(3) = {explored}; |
| 159 |
varargout(4) = {Vt}; |
| 160 |
varargout(5) = {CAREXTRA}; |
| 161 |
end %switch |
| 162 |
|
| 163 |
|
| 164 |
|
| 165 |
|
| 166 |
|
| 167 |
|
| 168 |
|
| 169 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
| 170 |
% This function computes the 3D dV volume elements. |
| 171 |
% Copy of the subfct_getDV function from gmaze_pv package |
| 172 |
function DV = local_getdV(Z,Y,X) |
| 173 |
|
| 174 |
nz = length(Z); |
| 175 |
ny = length(Y); |
| 176 |
nx = length(X); |
| 177 |
|
| 178 |
DV = zeros(nz,ny,nx); |
| 179 |
|
| 180 |
% Vertical elements: |
| 181 |
for iz = 1 : nz % Toward the deep ocean (because DPT<0) |
| 182 |
% Vertical grid length centered at Z(iy) |
| 183 |
if iz == 1 |
| 184 |
dz = abs(Z(1)) + abs(sum(diff(Z(iz:iz+1))/2)); |
| 185 |
elseif iz == nz % We don't know the real ocean depth |
| 186 |
dz = abs(sum(diff(Z(iz-1:iz))/2)); |
| 187 |
else |
| 188 |
dz = abs(sum(diff(Z(iz-1:iz+1))/2)); |
| 189 |
end |
| 190 |
DZ(iz) = dz; |
| 191 |
end |
| 192 |
|
| 193 |
% Surface and Volume elements: |
| 194 |
for ix = 1 : nx |
| 195 |
for iy = 1 : ny |
| 196 |
% Zonal grid length centered in X(ix),Y(iY) |
| 197 |
if ix == 1 |
| 198 |
dx = abs(m_lldist([X(ix) X(ix+1)],[1 1]*Y(iy)))/2; |
| 199 |
elseif ix == nx |
| 200 |
dx = abs(m_lldist([X(ix-1) X(ix)],[1 1]*Y(iy)))/2; |
| 201 |
else |
| 202 |
dx = abs(m_lldist([X(ix-1) X(ix)],[1 1]*Y(iy)))/2+abs(m_lldist([X(ix) X(ix+1)],[1 1]*Y(iy)))/2; |
| 203 |
end |
| 204 |
|
| 205 |
% Meridional grid length centered in X(ix),Y(iY) |
| 206 |
if iy == 1 |
| 207 |
dy = abs(m_lldist([1 1]*X(ix),[Y(iy) Y(iy+1)]))/2; |
| 208 |
elseif iy == ny |
| 209 |
dy = abs(m_lldist([1 1]*X(ix),[Y(iy-1) Y(iy)]))/2; |
| 210 |
else |
| 211 |
dy = abs(m_lldist([1 1]*X(ix),[Y(iy-1) Y(iy)]))/2+abs(m_lldist([1 1]*X(ix),[Y(iy) Y(iy+1)]))/2; |
| 212 |
end |
| 213 |
|
| 214 |
% Surface element: |
| 215 |
DA = dx*dy.*ones(1,nz); |
| 216 |
|
| 217 |
% Volume element: |
| 218 |
DV(:,iy,ix) = DZ.*DA; |
| 219 |
end %for iy |
| 220 |
end %for ix |
| 221 |
|