1 |
gmaze |
1.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 |
|
|
|