/[MITgcm]/MITgcm_contrib/dfer/matlab_stuff/calcHeatTransDirect.m
ViewVC logotype

Annotation of /MITgcm_contrib/dfer/matlab_stuff/calcHeatTransDirect.m

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.3 - (hide annotations) (download)
Thu Apr 19 00:03:59 2018 UTC (7 years, 3 months ago) by dfer
Branch: MAIN
CVS Tags: HEAD
Changes since 1.2: +5 -1 lines
Some minor updates

1 dfer 1.1 function HT = calcHeatTransDirect(varargin)
2    
3 dfer 1.2 % HT = calcHeatTransDirect(d,g,dE,GM,time,flu,blkFile,[mask,phi_ref]);
4 dfer 1.1 %
5     % Input arguements:
6     % The incoming field data (d) and grid data (g) must be in a structured
7     % array format (which is the format that comes from rdmnc):
8 dfer 1.2 % d [Structure] Various inputs depending on oceanic or
9     % atmospheric computation, rstar or not,
10     % and GM form/ouputs
11     % g [Structure] drF,dxG,dyG,dxC,dyC,HFacW,HFacS,rA
12     % dE [Structure] More field data
13     % GM [Structure] Gent anf McWilliams data
14 dfer 1.1 % Other input parameters:
15 dfer 1.2 % time [vector] Time levels to analyze ([] for all)
16     % flu [string] 'O' or 'A' for ocean or atmosphere
17     % blkFile [string] Broken line file (eg 'isoLat_cs32_59.mat')
18 dfer 1.1 % Optional parameters:
19 dfer 1.2 % mask [Structure] W and S mask
20     % phi_ref [vector] Reference geopotential height
21 dfer 1.1 %
22     % Output:
23     % HT_Out is a structured array with the following fields:
24     % time ([nt,1]) Time axis
25     % ylatHT ([ny,1]) Heat transport latitude axis
26     % ylatSF ([ny-1,1]) Implied heating latitude axis
27     % AreaZon ([ny,1]) Area in zonal bands
28     % SenHT ([ny,nBas,nt,nFld]) Sensible heat transport
29     % SenSF ([ny-1,nBas,nt,nFld]) Implied heating above
30     % LatHT ([ny,nBas,nt,nFld]) Latent heat transport (atm only)
31     % LatSF ([ny-1,nBas,nt,nFld]) Implied heating from aboce (atm only)
32     % Currently, the routine is only configured to handle the global basin,
33     % so nBas = 1 for the output. ny is defined by the broken line file used
34     % for the cube calculation. nFld is the heat transport component:
35     % nFld = 1 = Eulerian circulation HT
36     % nFld = 2 = HT by time mean circulation
37     % nFld = 3 = Residual [3=1-2]
38     % nFld = 4 = HT by zonal mean circulation
39     % nFld = 5 = Residual [5=2-4]
40     % Ocn only:
41     % If GM advective form:
42 dfer 1.3 % nFld = 6 = total (GM+Redi) eddy transport: K*dT/dy
43     % WARNING: This assumes K_gm=K_iso to get
44     % the cancellation of the off-diagonal term
45     % (K_iso-K_gm)*S_y*dT/dz
46     % nFld = 7 = GM (advective) eddy transport
47 dfer 1.1 % If Skew flux form:
48     % nFld = 6 = total (GM+Redi) eddy transport
49     % nFld = 7 = GM (advective) eddy transport
50     %
51     % Description:
52     % Calculation heat transport, and to degree possible, decomposition.
53     % Heat transport is given in PW and the implied surface heating/flux
54     % in W/m^2. The incoming data arrays are all assumed to be of the
55     % dimensions [6*nc,nc,nr,nt].
56     %
57     % Original Author: Jean-Michel Campin
58     % Modifications: Daniel Enderton
59    
60     % Default constants
61     LhVap = 2501;
62     grav = 9.81;
63     CpO = 3994;
64     RhoO = 1030;
65     CpA = 1004;
66     kappa = 2/7;
67     masking=0;
68    
69     PHIref = grav * [ 431.199 2105.998 5536.327 10440.915 18190.889];
70     %PHIref = grav * [ 173.888 529.598 896.724 1276.210 1669.052 ...
71     % 2076.380 2499.554 2940.137 3399.937 3881.061 ...
72     % 4385.993 4917.689 5480.084 6078.962 6722.700 ...
73     % 7420.744 8183.151 9023.181 9959.131 11019.028...
74     % 12253.003 13723.604 15599.238 18412.089 24539.570];
75    
76     % Read input parameters.
77     d = varargin{1};
78     g = varargin{2};
79     dE= varargin{3};
80     GM= varargin{4};
81     nt= varargin{5};
82     flu = varargin{6};
83     blkFile = varargin{7};
84     if length(varargin) >= 8 & ~isempty(varargin{8})
85     mask = varargin{8};
86     masking = 1;
87     disp('Masking is on...')
88     end
89     if length(varargin) == 9
90     PHIref= varargin{9};
91     end
92    
93     nBas = 0;
94     if isequal(flu,'A'), nout = 5; end
95     if isequal(flu,'O'), nout = 7; end
96     flag_tot=0;
97     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
98     % Prepare / reform incoming data %
99     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
100    
101     % Determine time indecies.
102     %if isempty(time), time = d.iters_read_from_file; i_time = 1:length(time);
103     %else [dump,i_time] = ismember(time,d.iters_read_from_file); end
104    
105     nc = size(g.HFacC,2);
106     nr = size(g.HFacC,3);
107     i_time=1:nt;
108    
109     if nr~=5
110     LhVap = 2500e3;
111     grav = 9.79764;
112     RDGAS = 287.04;
113     CpA = RDGAS/kappa;
114     end
115    
116     ac = reshape(g.rA ,[6*nc*nc, 1]);
117     hw = reshape(g.HFacW(1:6*nc,1:nc,1:nr),[6*nc*nc,nr]);
118     hs = reshape(g.HFacS(1:6*nc,1:nc,1:nr),[6*nc*nc,nr]);
119     dxc = reshape(g.dxC(1:6*nc,1:nc) ,[6*nc*nc, 1]);
120     dyc = reshape(g.dyC(1:6*nc,1:nc) ,[6*nc*nc, 1]);
121     dxg = reshape(g.dxG(1:6*nc,1:nc) ,[6*nc*nc, 1]);
122     dyg = reshape(g.dyG(1:6*nc,1:nc) ,[6*nc*nc, 1]);
123     drf = reshape(g.drF,[1,length(g.drF)]);
124     Z = reshape(g.Z,[1,length(g.Z)]);
125    
126     %u = reshape(d.UVEL(1:6*nc,1:nc,:,i_time),[6*nc*nc,nr,nt]);
127     %v = reshape(d.VVEL(1:6*nc,1:nc,:,i_time),[6*nc*nc,nr,nt]);
128     ut = reshape(dE.UTHMASS(1:6*nc,1:nc,:,i_time) ,[6*nc*nc,nr,nt]);
129     vt = reshape(dE.VTHMASS(1:6*nc,1:nc,:,i_time) ,[6*nc*nc,nr,nt]);
130     hu = reshape(dE.UVELMASS(1:6*nc,1:nc,:,i_time) ,[6*nc*nc,nr,nt]);
131     hv = reshape(dE.VVELMASS(1:6*nc,1:nc,:,i_time) ,[6*nc*nc,nr,nt]);
132     t = d.THETA(1:6*nc,1:nc,:,i_time);
133     if isequal(flu,'O')
134     Kux = reshape(GM.GM_Kux(1:6*nc,1:nc,:,i_time),[6*nc*nc,nr,nt]);
135     Kvy = reshape(GM.GM_Kvy(1:6*nc,1:nc,:,i_time),[6*nc*nc,nr,nt]);
136    
137     if isfield(GM,'GM_ubT') %%% if advective form of GM
138     UbTgm = reshape(GM.GM_ubT(1:6*nc,1:nc,:,i_time),[6*nc*nc,nr,nt]);
139     VbTgm = reshape(GM.GM_vbT(1:6*nc,1:nc,:,i_time),[6*nc*nc,nr,nt]);
140     elseif isfield(GM,'GM_KuzTz') %%% if skew-flux form of GM
141     UbTgm = reshape(GM.GM_KuzTz(1:6*nc,1:nc,:,i_time),[6*nc*nc,nr,nt]);
142     VbTgm = reshape(GM.GM_KvzTz(1:6*nc,1:nc,:,i_time),[6*nc*nc,nr,nt]);
143     elseif isfield(dE,'ADVx_TH') %%% if total advective field
144     flag_tot = 1;
145     UbTgm = reshape(dE.ADVx_TH(1:6*nc,1:nc,:,i_time),[6*nc*nc,nr,nt]);
146     VbTgm = reshape(dE.ADVy_TH(1:6*nc,1:nc,:,i_time),[6*nc*nc,nr,nt]);
147     else
148     UbTgm = zeros(6*nc*nc,nr,nt);
149     VbTgm = zeros(6*nc*nc,nr,nt);
150     end
151     end
152    
153     if isequal(flu,'A')
154     up = reshape(dE.UVELPHI(1:6*nc,1:nc,:,i_time) ,[6*nc*nc,nr,nt]);
155     vp = reshape(dE.VVELPHI(1:6*nc,1:nc,:,i_time) ,[6*nc*nc,nr,nt]);
156     uq = reshape(dE.USLTMASS(1:6*nc,1:nc,:,i_time) ,[6*nc*nc,nr,nt]);
157     vq = reshape(dE.VSLTMASS(1:6*nc,1:nc,:,i_time) ,[6*nc*nc,nr,nt]);
158     q = d.SALT(1:6*nc,1:nc,:,i_time);
159     p = d.PHIHYD(1:6*nc,1:nc,:,i_time);
160     ut = ut .* ( repmat(Z,[6*nc*nc 1 nt]) / 1e5 ).^kappa;
161     vt = vt .* ( repmat(Z,[6*nc*nc 1 nt]) / 1e5 ).^kappa;
162     t = t .* ( repmat(reshape(Z,[1 1 nr]),[6*nc nc 1 nt]) / 1e5 ).^kappa;
163     end
164    
165     if masking == 1
166     hu = repmat(reshape(mask.maskW(:,:,1),6*nc*nc,1),[1 nr nt]) .* hu;
167     hv = repmat(reshape(mask.maskS(:,:,1),6*nc*nc,1),[1 nr nt]) .* hv;
168     ut = repmat(reshape(mask.maskW(:,:,1),6*nc*nc,1),[1 nr nt]) .* ut;
169     vt = repmat(reshape(mask.maskS(:,:,1),6*nc*nc,1),[1 nr nt]) .* vt;
170     if isequal(flu,'O')
171     Kux = repmat(reshape(mask.maskW(:,:,1),6*nc*nc,1),[1 nr nt]) .* Kux;
172     Kvy = repmat(reshape(mask.maskS(:,:,1),6*nc*nc,1),[1 nr nt]) .* Kvy;
173     UbTgm = repmat(reshape(mask.maskW(:,:,1),6*nc*nc,1),[1 nr nt]) .* UbTgm;
174     VbTgm = repmat(reshape(mask.maskS(:,:,1),6*nc*nc,1),[1 nr nt]) .* VbTgm;
175     end
176     end
177    
178    
179     % Load broken line information. Compute (tracer point) cell area between
180     % broken lines for each basin. There are nbkl broken lines and nbkl+1
181     % bands between broken lines. The variable "bkl_Zon" gives the zone number
182     % (nbkl+1 total) for a given index between 0 and nbkl, that is, nbkl+1
183     % total zones. Comments block is for eventual addition of multiple basin
184     % calculations.
185     load(blkFile);
186     ydim=length(bkl_Ylat);
187     AreaZon=zeros(ydim+1,1+nBas);
188     for j = 1:ydim+1
189     izon = find(bkl_Zon == j-1);
190     AreaZon(j,1) = sum(ac(izon));
191     % for b = 1:nBas,
192     % tmp = ac.*mskBc(:,b);
193     % AreaZon(j,1+b) = sum(tmp(izon));
194     % end
195     end
196    
197     % Latitute plotting information. Average latitude of a broken line
198     % (ylatHF) is calculated from a mean value of the y value of all the edges.
199     % The latitude at the surface flux points is a mean of the broken line mean
200     % values.
201     YlatAv=sum(bkl_Ysg,1)./(1+bkl_Npts'); %'
202     ylatHT = [-90,YlatAv,90];
203     ylatSF = ( ylatHT(2:ydim+2) + ylatHT(1:ydim+1) )./2;
204    
205     % The variable "bkl_Flg" is -1/1 if edge (on a given broken) has a u point
206     % and -2/2 if it has a v point. Positive/negative values contribute
207     % positively/negatively to northward heat transport (this depends on the
208     % orientation of the cell). A zero value indicates an end of edges that
209     % contribute to a broken line. The u and v information is parced into two
210     % seperate fields, ufac and vfac (-2/2 are reduced to -1/1 for vfac).
211     ufac = zeros([size(bkl_Flg),1+nBas]);
212     vfac = zeros([size(bkl_Flg),1+nBas]);
213     ufac(:,:,1) = rem(bkl_Flg,2);
214     vfac(:,:,1) = fix(bkl_Flg/2);
215     % for jl=1:ydim,
216     % ie=bkl_Npts(jl);
217     % for b=1:nBas,
218     % ufac(1:ie,jl,1+b)=mskBw(bkl_IJuv(1:ie,jl),b).*ufac(1:ie,jl,1);
219     % vfac(1:ie,jl,1+b)=mskBs(bkl_IJuv(1:ie,jl),b).*vfac(1:ie,jl,1);
220     % end
221     % end
222     ufacabs = abs(ufac);
223     vfacabs = abs(vfac);
224    
225     % Prepare mask(s).
226     % ??? I temporarily took out the code to configure the masks beyond this
227     % global one. Does this need to account for a ridge if present?
228     mskG=ones(ydim+1,1+nBas);
229    
230     % Area factors. "ArW_Dif" and "ArS_Dif" the areas for the western and
231     % southern edge of cells, respectively The "_Dif" suffix indicates the
232     % areas used for the diffusivity because there is an extra "dxc" or "dyc"
233     % from the gradient (here for computational efficiency reasons). The
234     % division by "dxc" and "dyc" is associates with gradient of temperature.
235     %
236     % ??? Why is the land mask (hw and hs) only in the diffusive area term?
237     ArW = dyg*reshape(drf,[1,length(drf)]);
238     ArS = dxg*reshape(drf,[1,length(drf)]);
239     ArW_Dif=hw.*((dyg./dxc)*reshape(drf,[1,length(drf)]));
240     ArS_Dif=hs.*((dxg./dyc)*reshape(drf,[1,length(drf)]));
241    
242     % Compute the temperature and its gradient and the velocity points:
243     % tbi/tdi = temperature between/difference i points (at u points)
244     % tbj/tdj = temperature between/difference j points (at v points)
245     % The cube is first split and the extra points are added to the files.
246     % Then the means and differences are taken. Note that the division of dxc
247     % and dyc for the gradient is not applied until later for computational
248     % efficiency purposes. The arrays are then croped and reshaped to the
249     % format for the other field variables, [6*nc*nc,nr]. Note that the
250     % split_C_cub function adds a row/column of tracer points in front of the
251     % first row/column of the tile matries. This, when the differences and
252     % gradients are computed and cropped, the off indecies are selected from
253     % [2:nc+1] rather than [1:nc]. (This was a bit mystifying to me).
254     t6bi=zeros(nc,nc+1,nr,nt,6); t6di=t6bi; q6bi=t6bi;
255     t6bj=zeros(nc+1,nc,nr,nt,6); t6dj=t6bj; q6bj=t6bj;
256     t6t=split_C_cub(t);
257     t6bi([1:nc],:,:,:,:) = ( t6t([1:nc],:,:,:,:) + t6t([2:nc+1],:,:,:,:) )./2;
258     t6bj(:,[1:nc],:,:,:) = ( t6t(:,[1:nc],:,:,:) + t6t(:,[2:nc+1],:,:,:) )./2;
259     t6di([1:nc],:,:,:,:) = ( t6t([1:nc],:,:,:,:) - t6t([2:nc+1],:,:,:,:) );
260     t6dj(:,[1:nc],:,:,:) = ( t6t(:,[1:nc],:,:,:) - t6t(:,[2:nc+1],:,:,:) );
261     tbi = t6bi([1:nc],[2:nc+1],:,:,:);
262     tbj = t6bj([2:nc+1],[1:nc],:,:,:);
263     tdi = t6di([1:nc],[2:nc+1],:,:,:);
264     tdj = t6dj([2:nc+1],[1:nc],:,:,:);
265     tbi=reshape(permute(tbi,[1,5,2,3,4]),[6*nc*nc,nr,nt]);
266     tbj=reshape(permute(tbj,[1,5,2,3,4]),[6*nc*nc,nr,nt]);
267     tdi=reshape(permute(tdi,[1,5,2,3,4]),[6*nc*nc,nr,nt]);
268     tdj=reshape(permute(tdj,[1,5,2,3,4]),[6*nc*nc,nr,nt]);
269     if isequal(flu,'A')
270     q6t=split_C_cub(q);
271     q6bi([1:nc],:,:,:,:) = (q6t([1:nc],:,:,:,:)+q6t([2:nc+1],:,:,:,:))./2;
272     q6bj(:,[1:nc],:,:,:) = (q6t(:,[1:nc],:,:,:)+q6t(:,[2:nc+1],:,:,:))./2;
273     qbi = q6bi([1:nc],[2:nc+1],:,:,:);
274     qbj = q6bj([2:nc+1],[1:nc],:,:,:);
275     qbi=reshape(permute(qbi,[1,5,2,3,4]),[6*nc*nc,nr,nt]);
276     qbj=reshape(permute(qbj,[1,5,2,3,4]),[6*nc*nc,nr,nt]);
277    
278     p6t=split_C_cub(p);
279     p6bi([1:nc],:,:,:,:) = (p6t([1:nc],:,:,:,:)+p6t([2:nc+1],:,:,:,:))./2;
280     p6bj(:,[1:nc],:,:,:) = (p6t(:,[1:nc],:,:,:)+p6t(:,[2:nc+1],:,:,:))./2;
281     pbi = p6bi([1:nc],[2:nc+1],:,:,:);
282     pbj = p6bj([2:nc+1],[1:nc],:,:,:);
283     pbi=reshape(permute(pbi,[1,5,2,3,4]),[6*nc*nc,nr,nt]);
284     pbj=reshape(permute(pbj,[1,5,2,3,4]),[6*nc*nc,nr,nt]);
285     end
286    
287     % Prepare output arrays. "nout" is the number of transport output fields.
288     % It is currently hard-coded, but could eventually be an input parameters
289     % to set which output fields are desired if some of then become
290     % computationally expensive.
291     % SenHT = Sensible heat transport
292     % SenSF = Sensible implied surface flux
293     % IntV = Integrated volume transport
294     % IntT = Integrated temperature
295     SenHT = zeros(ydim+2,1+nBas,nt,nout);
296     SenSF = zeros(ydim+1,1+nBas,nt,nout);
297     IntV = zeros(ydim,nr,1+nBas,nt);
298     IntT = zeros(ydim,nr,1+nBas,nt);
299     IntM = zeros(ydim,nr,1+nBas,nt);
300     if isequal(flu,'A')
301     LatHT = zeros(ydim+2,1+nBas,nt,nout);
302     PotHT = zeros(ydim+2,1+nBas,nt,nout);
303     LatSF = zeros(ydim+1,1+nBas,nt,nout);
304     IntQ = zeros(ydim,nr,1+nBas,nt);
305     IntP = zeros(ydim,nr,1+nBas,nt);
306     end
307     Psi = zeros(ydim+2,1+nBas,nt);
308    
309     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
310     % Make heat transport calculations %
311     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
312    
313     % Preparation for calculation of zonal average temperature. The
314     % tempereature multiplied by the appropriate length scale ("tbi_temp",
315     % "tbj_temp") is summed up ("IntT" in the next section) and
316     % divided by the total length ("IntM", composed from summing "hw_temp",
317     % "hs_temp").
318     hw_temp = zeros(size(hw));
319     hs_temp = zeros(size(hs));
320     for k=1:nr,
321     hw_temp(:,k) = dyg.*hw(:,k);
322     hs_temp(:,k) = dxg.*hs(:,k);
323     end
324    
325     for it = 1:length(i_time)
326    
327     % uz / vz = Volume transport though cell faces (velocity times area).
328     % Used for zonal mean volume transport (4).
329     % utz1/vtz1 = Eulerian sensible heat transport through cell faces (1).
330     % utz2/vtz2 = Sensible heat transport through cell faces by Eulerian
331     % mean circulations (2).
332     % dtx1/dty1 = Temperatude gradient at cell face times the area (when
333     % multiplied by the diffusion will be the horizontal
334     % diffusion heat transport) (6).
335     uz = ArW.*hu(:,:,it);
336     vz = ArS.*hv(:,:,it);
337     utz1 = sum(ArW.*ut(:,:,it),2);
338     vtz1 = sum(ArS.*vt(:,:,it),2);
339     utz2 = sum(ArW.*hu(:,:,it).*tbi(:,:,it),2);
340     vtz2 = sum(ArS.*hv(:,:,it).*tbj(:,:,it),2);
341     if isequal(flu,'A')
342     uqz1 = sum(ArW.*uq(:,:,it),2);
343     vqz1 = sum(ArS.*vq(:,:,it),2);
344     uqz2 = sum(ArW.*hu(:,:,it).*qbi(:,:,it),2);
345     vqz2 = sum(ArS.*hv(:,:,it).*qbj(:,:,it),2);
346     upz1 = sum(ArW.*(up(:,:,it)+hu(:,:,it).*repmat(PHIref,[6*nc*nc 1])),2);
347     vpz1 = sum(ArS.*(vp(:,:,it)+hv(:,:,it).*repmat(PHIref,[6*nc*nc 1])),2);
348     upz2 = sum(ArW.*hu(:,:,it).*(pbi(:,:,it)+repmat(PHIref,[6*nc*nc 1])),2);
349     vpz2 = sum(ArS.*hv(:,:,it).*(pbj(:,:,it)+repmat(PHIref,[6*nc*nc 1])),2);
350     end
351     if isequal(flu,'O')
352     dtx1 = sum(ArW_Dif.*Kux(:,:,it).*tdi(:,:,it),2);
353     dty1 = sum(ArS_Dif.*Kvy(:,:,it).*tdj(:,:,it),2);
354     Kuztz1 = sum(UbTgm(:,:,it),2);
355     Kvztz1 = sum(VbTgm(:,:,it),2);
356     end
357    
358     % Preparation for calculation of zonal average temperature. The
359     % temperature multiplied by the appropriate length scale ("tbi_temp",
360     % "tbj_temp") is summed up ("IntT" in the next section) and
361     % divided by the total length ("IntM", composed from summing "hw_temp",
362     % "hs_temp").
363     tbi_temp = hw_temp.*tbi(:,:,it);
364     tbj_temp = hs_temp.*tbj(:,:,it);
365     if isequal(flu,'A')
366     qbi_temp = hw_temp.*qbi(:,:,it);
367     qbj_temp = hs_temp.*qbj(:,:,it);
368     pbi_temp = hw_temp.*(pbi(:,:,it)+repmat(PHIref,[6*nc*nc 1]));
369     pbj_temp = hs_temp.*(pbj(:,:,it)+repmat(PHIref,[6*nc*nc 1]));
370     end
371    
372     % Block 1:
373     % With the vertical integral of heat transport calculated across cell
374     % edges, the zonal integral (along the broken line) is computed to
375     % determine the total northward heat transport. The first for loop is
376     % over the individual broken lines (determining the northward HT at the
377     % representative latitude). The second loop is over the basins. The
378     % third loop is over the individual edges along a specific broken line.
379     % Note that an individual cell can have two edges (u and v) that have a
380     % HT contributions. Hence the variable containing indecies of cells
381     % with edges along the broken lines, "bkl_IJuv", has some repeats.
382     % Note that the variable "bkl_Npts" is the number of edges along a
383     % given broken line. Note also that the latitude axis starts at 2
384     % because heat transport at extremes (latitute = -90/90) is zero by
385     % definition. Recall that index (1) is total Eulerian transport, (2)
386     % is from the mean circulations, and (3) is from the horizontal
387     % diffusion.
388     %
389     % Block 2:
390     % Here zonal average circulation and temperature / moisture is
391     % calculated. The zonal average volume transport v (IntV) and t
392     % (IntT/IntM) are computed first and are multiplied together at the
393     % end.
394     for jl=1:ydim
395     ie=bkl_Npts(jl);
396     for b=1:1+nBas
397     ij=bkl_IJuv(1:ie,jl);
398     % Block 1:
399     SenHT(1+jl,b,it,1) = SenHT(1+jl,b,it,1) + ...
400     sum(ufac(1:ie,jl,b).*utz1(ij) + ...
401     vfac(1:ie,jl,b).*vtz1(ij));
402     SenHT(1+jl,b,it,2) = SenHT(1+jl,b,it,2) + ...
403     sum(ufac(1:ie,jl,b).*utz2(ij) + ...
404     vfac(1:ie,jl,b).*vtz2(ij));
405     if isequal(flu,'A')
406     LatHT(1+jl,b,it,1) = LatHT(1+jl,b,it,1) + ...
407     sum(ufac(1:ie,jl,b).*uqz1(ij) + ...
408     vfac(1:ie,jl,b).*vqz1(ij));
409     LatHT(1+jl,b,it,2) = LatHT(1+jl,b,it,2) + ...
410     sum(ufac(1:ie,jl,b).*uqz2(ij) + ...
411     vfac(1:ie,jl,b).*vqz2(ij));
412     PotHT(1+jl,b,it,1) = PotHT(1+jl,b,it,1) + ...
413     sum(ufac(1:ie,jl,b).*upz1(ij) + ...
414     vfac(1:ie,jl,b).*vpz1(ij));
415     PotHT(1+jl,b,it,2) = PotHT(1+jl,b,it,2) + ...
416     sum(ufac(1:ie,jl,b).*upz2(ij) + ...
417     vfac(1:ie,jl,b).*vpz2(ij));
418     end
419     if isequal(flu,'O')
420     SenHT(1+jl,b,it,6) = SenHT(1+jl,b,it,6) + ...
421     sum(ufac(1:ie,jl,b).*dtx1(ij) + ...
422     vfac(1:ie,jl,b).*dty1(ij));
423     SenHT(1+jl,b,it,7) = SenHT(1+jl,b,it,7) + ...
424     sum(ufac(1:ie,jl,b).*Kuztz1(ij) + ...
425     vfac(1:ie,jl,b).*Kvztz1(ij));
426     end
427     % Block 2:
428     IntV(jl,:,b,it) = IntV(jl,:,b,it) ...
429     + ufac(1:ie,jl,b)'*uz(ij,:) ...
430     + vfac(1:ie,jl,b)'*vz(ij,:) ;
431     IntT(jl,:,b,it) = IntT(jl,:,b,it) ...
432     + ufacabs(1:ie,jl,b)'*tbi_temp(ij,:) ...
433     + vfacabs(1:ie,jl,b)'*tbj_temp(ij,:);
434     IntM(jl,:,b,it) = IntM(jl,:,b,it) ...
435     + ufacabs(1:ie,jl,b)'*hw_temp(ij,:) ...
436     + vfacabs(1:ie,jl,b)'*hs_temp(ij,:);
437     if isequal(flu,'A')
438     IntQ(jl,:,b,it) = IntQ(jl,:,b,it) ...
439     + ufacabs(1:ie,jl,b)'*qbi_temp(ij,:) ...
440     + vfacabs(1:ie,jl,b)'*qbj_temp(ij,:);
441     IntP(jl,:,b,it) = IntP(jl,:,b,it) ...
442     + ufacabs(1:ie,jl,b)'*pbi_temp(ij,:) ...
443     + vfacabs(1:ie,jl,b)'*pbj_temp(ij,:);
444     end
445     end
446     end
447    
448     % Prepare HT output: Calculate HT by zonal flows and tabulate
449     % residuals. Also, the multiplicative constants (Cp,rho,grav,LhVap) are
450     % applied here to put moisture and potential temperature fluxes in
451     % terms of heat transports.
452     tmp = IntV(:,:,:,it) .* IntT(:,:,:,it) ...
453     ./ change(IntM(:,:,:,it),'==',0,NaN);
454     SenHT(2:ydim+1,:,it,4) = sum(change(tmp,'==',NaN,0),2);
455     % SenHT(2:ydim+1,:,it,4) = sum( IntV(:,:,:,it) ...
456     % .* IntT(:,:,:,it) ...
457     % ./ IntM(:,:,:,it),2);
458     SenHT(:,:,it,3) = SenHT(:,:,it,1) - SenHT(:,:,it,2);
459     SenHT(:,:,it,5) = SenHT(:,:,it,2) - SenHT(:,:,it,4);
460     if isequal(flu,'O')
461     % SenHT(:,:,it,6) = DiffKh.*SenHT(:,:,it,6);
462     SenHT(:,:,it,:) = (CpO*RhoO)*SenHT(:,:,it,:);
463     if flag_tot==1
464     SenHT(:,:,it,7)=SenHT(:,:,it,7)-SenHT(:,:,it,1);
465     end
466     elseif isequal(flu,'A')
467     SenHT(:,:,it,:) = (CpA./grav).*SenHT(:,:,it,:);
468     LatHT(2:ydim+1,:,it,4) = sum( IntV(:,:,:,it) ...
469     .* IntQ(:,:,:,it) ...
470     ./ IntM(:,:,:,it),2);
471     LatHT(:,:,it,3) = LatHT(:,:,it,1) - LatHT(:,:,it,2);
472     LatHT(:,:,it,5) = LatHT(:,:,it,2) - LatHT(:,:,it,4);
473     LatHT(:,:,it,:) = (LhVap./grav).*LatHT(:,:,it,:);
474    
475     PotHT(2:ydim+1,:,it,4) = sum( IntV(:,:,:,it) ...
476     .* IntP(:,:,:,it) ...
477     ./ IntM(:,:,:,it),2);
478     PotHT(:,:,it,3) = PotHT(:,:,it,1) - PotHT(:,:,it,2);
479     PotHT(:,:,it,5) = PotHT(:,:,it,2) - PotHT(:,:,it,4);
480     PotHT(:,:,it,:) = 1/grav * PotHT(:,:,it,:);
481     end
482     Psi(2:ydim+1,:,it) = - sum( IntV(:,:,:,it) ,2 );
483    
484     % Implied surface heat flux from heat transports (implied heating).
485     % Tabulated as the difference in heat transports between two broken
486     % lines divided by the zonal band area.
487     mskG = reshape(mskG,(ydim+1)*(1+nBas),1);
488     I = find(mskG==0);
489     mskG = reshape(mskG,ydim+1,1+nBas);
490     var = zeros(ydim+1,1+nBas);
491     for n=1:min(nout,6),
492     varT = SenHT([2:ydim+2],:,it,n) ...
493     - SenHT([1:ydim+1],:,it,n);
494     varT = reshape(varT,(ydim+1)*(1+nBas),1); varT(I)=NaN;
495     varT = reshape(varT,ydim+1,1+nBas);
496     SenSF([1:ydim+1],:,it,n) = varT./AreaZon;
497     if isequal(flu,'A')
498     for n=1:min(nout,6)
499     varQ = LatHT([2:ydim+2],:,it,n) ...
500     - LatHT([1:ydim+1],:,it,n);
501     varQ = reshape(varQ,(ydim+1)*(1+nBas),1); varQ(I)=NaN;
502     varQ = reshape(varQ,ydim+1,1+nBas);
503     LatSF([1:ydim+1],:,it,n) = varQ./AreaZon;
504     end
505     end
506     end
507     end
508    
509    
510     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
511     % Assign outputs, put in units of PW %
512     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
513    
514     SenHT = SenHT*1e-15;
515    
516     HT.time = i_time;
517     HT.SenHT = reshape(SenHT,ydim+2,nt,nout);
518     HT.SenSF = reshape(SenSF,ydim+1,nt,nout);
519     HT.ylatHT = ylatHT;
520     HT.ylatSF = ylatSF;
521     HT.AreaZon = AreaZon;
522     HT.PsiSurf = 1e-6*reshape(Psi,ydim+2,nt);
523    
524     if isequal(flu,'A')
525     LatHT = LatHT*1e-15;
526     PotHT = PotHT*1e-15;
527     HT.LatHT = reshape(LatHT,ydim+2,nt,nout);
528     HT.LatSF = reshape(LatSF,ydim+1,nt,nout);
529     HT.PotHT = reshape(PotHT,ydim+2,nt,nout);
530     end
531    

  ViewVC Help
Powered by ViewVC 1.1.22