1 |
dfer |
1.1 |
function [psi,mskG,ylat] = calcEulerPsiCube(varargin); |
2 |
|
|
|
3 |
dfer |
1.3 |
% [psi,mskG,ylat] = calcEulerPsiCube(d,g,flu,rstar,blkFile,[mask]); |
4 |
dfer |
1.1 |
% |
5 |
dfer |
1.3 |
% Input arguments: |
6 |
|
|
% d [structure] Velocity field (Mass-weighted if rstar=1): |
7 |
|
|
% UVELMASS,VVELMASS for rstar=1 |
8 |
|
|
% UVEL,VVEL for rstar=0 |
9 |
|
|
% g [structure] drF,dxG,dyG,HFacW,HFacS |
10 |
|
|
% flu [string] 'O' or 'A' for ocean or atmosphere |
11 |
|
|
% rstar [integer] 1 or 0 if you are using r* coordinates or not |
12 |
|
|
% blkFile [string] Broken line file ('isoLat_cs32_59.mat') |
13 |
|
|
% |
14 |
|
|
% Optional inputs: |
15 |
|
|
% mask [structure] Optional: Mask field for computation per basin, it assumes that |
16 |
|
|
% maskW and maskS are provided in a structure |
17 |
dfer |
1.1 |
% |
18 |
|
|
% Output fields: |
19 |
dfer |
1.3 |
% psi Overturning |
20 |
|
|
% mskG Land mask |
21 |
|
|
% ylat Latitude coordinate of psi |
22 |
dfer |
1.1 |
% |
23 |
|
|
% Description: |
24 |
dfer |
1.3 |
% Calculates overturning streamfunction (psi). For the atmosphere, data |
25 |
dfer |
1.1 |
% is must be in p-coordinates and the output is the mass transport psi |
26 |
dfer |
1.3 |
% [10^9 kg/s]. For the ocean, data should be in z-coordinates and the |
27 |
|
|
% output is the volume transport psi [10^6 m^3/s = Sv]. If rstar |
28 |
|
|
% is on (=1), UVELMASS and VVELMASS must be used. If off (rstar=0), |
29 |
|
|
% the hfacw*.UVEL and hfacs*.VVEL are used (the multiplication being |
30 |
|
|
% done inside the function). |
31 |
dfer |
1.1 |
% |
32 |
|
|
% 'psi' is tabulated on broken lines at the interface between cells in |
33 |
dfer |
1.3 |
% the vertical. 'mskG' is for the area between broken lines and between |
34 |
dfer |
1.1 |
% the cell interfaces in the vertical. |
35 |
|
|
% |
36 |
|
|
|
37 |
|
|
% Defaults that can be overriden. |
38 |
|
|
grav = 9.81; |
39 |
|
|
masking=0; |
40 |
dfer |
1.3 |
nBas=0; |
41 |
dfer |
1.1 |
|
42 |
|
|
% Read input parameters. |
43 |
|
|
d = varargin{1}; |
44 |
|
|
g = varargin{2}; |
45 |
|
|
flu = varargin{3}; |
46 |
|
|
rstar = varargin{4}; |
47 |
|
|
blkFile = varargin{5}; |
48 |
|
|
if length(varargin) == 6 |
49 |
|
|
mask = varargin{6}; |
50 |
|
|
masking = 1; |
51 |
|
|
end |
52 |
|
|
|
53 |
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
54 |
|
|
% Prepare / reform incoming data % |
55 |
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
56 |
|
|
|
57 |
|
|
nc = size(g.XC,2); |
58 |
|
|
nr = length(g.drF); |
59 |
|
|
|
60 |
|
|
delM = g.drF; |
61 |
|
|
dxg = reshape(g.dxG(1:6*nc,1:nc),[6*nc*nc,1]); |
62 |
|
|
dyg = reshape(g.dyG(1:6*nc,1:nc),[6*nc*nc,1]); |
63 |
|
|
if rstar |
64 |
|
|
nt = size(d.UVELMASS,4); |
65 |
|
|
hu = reshape(d.UVELMASS(1:6*nc,1:nc,1:nr,1:nt),[6*nc*nc,nr,nt]); |
66 |
|
|
hv = reshape(d.VVELMASS(1:6*nc,1:nc,1:nr,1:nt),[6*nc*nc,nr,nt]); |
67 |
|
|
else |
68 |
|
|
nt = size(d.UVEL,4); |
69 |
|
|
hw = reshape(g.HFacW(1:6*nc,1:nc,1:nr),[6*nc*nc,nr]); |
70 |
|
|
hs = reshape(g.HFacS(1:6*nc,1:nc,1:nr),[6*nc*nc,nr]); |
71 |
|
|
hu = reshape(d.UVEL(1:6*nc,1:nc,1:nr,1:nt),[6*nc*nc,nr,nt]); |
72 |
|
|
hv = reshape(d.VVEL(1:6*nc,1:nc,1:nr,1:nt),[6*nc*nc,nr,nt]); |
73 |
|
|
for it = 1:nt |
74 |
|
|
hu(:,:,it) = hw.*hu(:,:,it); |
75 |
|
|
hv(:,:,it) = hs.*hv(:,:,it); |
76 |
|
|
end |
77 |
|
|
end |
78 |
|
|
|
79 |
|
|
mskWloc = ones(6*nc*nc,1); |
80 |
|
|
mskSloc = ones(6*nc*nc,1); |
81 |
|
|
|
82 |
|
|
if masking == 1 |
83 |
|
|
mskWloc=reshape(mask.maskW(:,:,1),6*nc*nc,1); |
84 |
|
|
mskSloc=reshape(mask.maskS(:,:,1),6*nc*nc,1); |
85 |
|
|
%hu = repmat(reshape(mask.maskW,6*nc*nc,1),[1 nr nt]) .* hu; |
86 |
|
|
%hv = repmat(reshape(mask.maskS,6*nc*nc,1),[1 nr nt]) .* hv; |
87 |
|
|
end |
88 |
|
|
|
89 |
|
|
% Load broken information. |
90 |
|
|
load(blkFile); |
91 |
|
|
ydim = length(bkl_Ylat); |
92 |
|
|
ylat = [-90,bkl_Ylat,90]; |
93 |
|
|
|
94 |
|
|
% Prepare arrays. |
95 |
|
|
psi = zeros(ydim+2,nr+1,1+nBas,nt); |
96 |
|
|
mskZ = zeros(ydim+2,nr+1,1+nBas); % Mask of psi |
97 |
|
|
mskV = zeros(ydim+2,nr,1+nBas); % Mask of the merid. transport |
98 |
|
|
mskG = zeros(ydim+1,nr,1+nBas); % Mask of the ground |
99 |
|
|
|
100 |
|
|
% The variable "bkl_Flg" is -1/1 if edge (on a given broken) has a u point |
101 |
|
|
% and -2/2 if it has a v point. Positive/negative values contribute |
102 |
|
|
% positively/negatively to northward heat transport (this depends on the |
103 |
|
|
% oreientation of the cell). A zero value indicates an end of edges that |
104 |
|
|
% contribute to a broken line. The u and v information is parced into two |
105 |
|
|
% seperate fields, ufac and vfac (-2/2 are reduced to -1/1 for vfac). |
106 |
|
|
ufac = zeros([size(bkl_Flg),1+nBas]); |
107 |
|
|
vfac = zeros([size(bkl_Flg),1+nBas]); |
108 |
|
|
ufac(:,:,1) = rem(bkl_Flg,2); |
109 |
|
|
vfac(:,:,1) = fix(bkl_Flg/2); |
110 |
|
|
|
111 |
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
112 |
|
|
% Compute mass/volume stream function % |
113 |
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
114 |
|
|
|
115 |
|
|
% Compute volume transport through broken lines a hence psi. ut/vt is the |
116 |
|
|
% velocity times the edge length it is passing through. The sum of this |
117 |
|
|
% quantity along a broken line (vz) times the cell height is the volume |
118 |
|
|
% transport through broken line at one layer (delM(k)*vz). psi is then |
119 |
|
|
% the value of the volume transport through the level above subtracted |
120 |
|
|
% from the value of psi above. |
121 |
|
|
for it = 1:nt |
122 |
|
|
for k = nr:-1:1 |
123 |
|
|
ut = dyg.*hu(:,k,it).*mskWloc; |
124 |
|
|
vt = dxg.*hv(:,k,it).*mskSloc; |
125 |
|
|
for jl = 1:ydim |
126 |
|
|
ie = bkl_Npts(jl); |
127 |
|
|
for b = 1:1+nBas |
128 |
|
|
vz = sum( ufac(1:ie,jl,b).*ut(bkl_IJuv(1:ie,jl)) ... |
129 |
|
|
+ vfac(1:ie,jl,b).*vt(bkl_IJuv(1:ie,jl)) ); |
130 |
|
|
psi(jl+1,k,b,it) = psi(jl+1,k+1,b,it) - delM(k)*vz; |
131 |
|
|
end |
132 |
|
|
end |
133 |
|
|
end |
134 |
|
|
end |
135 |
|
|
|
136 |
|
|
psi = squeeze(psi); |
137 |
|
|
|
138 |
|
|
%% For Ocean, result in Sv (10^6 m3/s) |
139 |
|
|
%% For Atmos, results in 10^9 kg/s |
140 |
|
|
if isequal(flu,'O'), psi = 1e-6*squeeze(psi); end |
141 |
|
|
if isequal(flu,'A'), psi =-1e-9/grav*squeeze(psi); end |
142 |
|
|
|