/[MITgcm]/MITgcm_contrib/gael/matlab_class/gcmfaces_smooth/diffsmooth2D_div_inv.m
ViewVC logotype

Annotation of /MITgcm_contrib/gael/matlab_class/gcmfaces_smooth/diffsmooth2D_div_inv.m

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


Revision 1.1 - (hide annotations) (download)
Thu May 6 20:24:32 2010 UTC (15 years, 2 months ago) by gforget
Branch: MAIN
diffsmooth2D_div_inv.m:
      compute divergent part of
      a transport vector field

1 gforget 1.1 function [fldUdiv,fldVdiv,fldDivPot]=diffsmooth2D_div_inv(fldU,fldV);
2    
3     %object: compute the divergent part of a tranport vector field
4     % by solving a Laplace equation with Neumann B.C.
5     %
6     %input: fldU,fldV transport vectors (masked with NaNs)
7     %output:fldUdiv,fldVdiv divergent part
8     % fldDivPot Potential for the divergent flow (optional)
9     %
10     %note 1: here we do everything in terms of transports, so we omit all
11     % grid factors (i.e. with dx=dy=1), and the resulting potential
12     % has usits of transports.
13     %note 2: this routine was derived from diffsmooth2D_extrap_inv.m but
14     % it differs in several aspects. It : 1) omits grid factors;
15     % 2) uses of a neumann, rather than dirichlet, boundary condition;
16     % 3) gets the mask directly from fld.
17    
18     global mygrid;
19    
20     fld=calc_UV_div(fldU,fldV,{});%no grid scaling factor in div. or transports
21     fld=fld.*mygrid.mskC(:,:,1);
22    
23     mskWet=fld; mskWet(~isnan(fld))=1;
24     mskDry=1*isnan(mskWet); mskDry(mskDry==0)=NaN;
25    
26     %check for domain edge points where no exchange is possible:
27     tmp1=mskWet; tmp1(:)=1; tmp2=exch_T_N(tmp1);
28     for iF=1:mskWet.nFaces;
29     tmp3=mskWet{iF}; tmp4=tmp2{iF};
30     tmp4=tmp4(2:end-1,1:end-2)+tmp4(2:end-1,3:end)+tmp4(1:end-2,2:end-1)+tmp4(3:end,2:end-1);
31     if ~isempty(find(isnan(tmp4)&~isnan(tmp3))); fprintf('warning: mask was modified\n'); end;
32     tmp3(isnan(tmp4))=NaN; mskWet{iF}=tmp3;
33     end;
34     %why does this matters... see set-ups with open boundary conditions...
35    
36     %put 0 first guess if needed and switch land mask:
37     fld(find(isnan(fld)))=0; fld=fld.*mskWet;
38    
39     %define mapping from global array to (no nan points) global vector
40     tmp1=convert2array(mskWet);
41     kk=find(~isnan(tmp1)); nn=length(kk);
42     KK=tmp1; KK(:)=0; KK(kk)=kk; KKfaces=convert2array(KK,fld); %global array indices
43     LL=tmp1; LL(:)=0; LL(kk)=[1:nn]; LLfaces=convert2array(LL,fld); %global vector indices
44    
45     %note: diffsmooth2D_extrap_inv.m uses a Dirichlet boundary condition
46     % so that it uses a nan/1 mask in KK/LL // here we use a
47     % Neumann boundary condition so we use a 0/1 mask (see below also)
48    
49     %form matrix problem:
50     A=sparse([],[],[],nn,nn,nn*5);
51     for iF=1:fld.nFaces; for ii=1:3; for jj=1:3;
52    
53     %1) seed points (FLDones) and neighborhood of influence (FLDkkFROM)
54     FLDones=fld; FLDones(:)=0;
55     FLDones{iF}(ii:3:end,jj:3:end)=1;
56     FLDones(KKfaces==0)=0;
57    
58     FLDkkFROMtmp=fld; FLDkkFROMtmp(:)=0;
59     FLDkkFROMtmp{iF}(ii:3:end,jj:3:end)=KKfaces{iF}(ii:3:end,jj:3:end);
60     FLDkkFROMtmp(find(isnan(fld)))=0;
61    
62     FLDkkFROM=exch_T_N(FLDkkFROMtmp); FLDkkFROM(isnan(FLDkkFROM))=0;
63     for iF2=1:fld.nFaces;
64     tmp1=FLDkkFROM{iF2}; tmp2=zeros(size(tmp1)-2);
65     for ii2=1:3; for jj2=1:3; tmp2=tmp2+tmp1(ii2:end-3+ii2,jj2:end-3+jj2); end; end;
66     FLDkkFROM{iF2}=tmp2;
67     end;
68    
69     %2) compute effect of each point on neighboring target point:
70     [tmpU,tmpV]=calc_T_grad(FLDones,0);
71     %unlike calc_T_grad, we work in grid point index, so we need to omit grid factors
72     tmpU=tmpU.*mygrid.DXC; tmpV=tmpV.*mygrid.DYC;
73     %and accordingly we use no grid scaling factor in div.
74     [dFLDdt]=calc_UV_div(tmpU,tmpV,{});
75    
76     %note: diffsmooth2D_extrap_inv.m uses a Dirichlet boundary condition
77     % so that it needs to apply mskFreeze to dFLDdt // here we use a
78     % Neumann boundary condition so we do not mask dFLDdt (see above also)
79    
80     %3) include seed contributions in matrix:
81     FLDkkFROM=convert2array(FLDkkFROM);
82     %3.1) for wet points
83     dFLDdtWet=convert2array(dFLDdt.*mskWet);
84     tmp1=find(dFLDdtWet~=0&~isnan(dFLDdtWet));
85     dFLDdtWet=dFLDdtWet(tmp1); FLDkkFROMtmp=FLDkkFROM(tmp1); FLDkkTOtmp=KK(tmp1);
86     A=A+sparse(LL(FLDkkTOtmp),LL(FLDkkFROMtmp),dFLDdtWet,nn,nn);
87     %3.2) for dry points (-> this part reflects the neumann boundary condition)
88     dFLDdtDry=convert2array(dFLDdt.*mskDry);
89     tmp1=find(dFLDdtDry~=0&~isnan(dFLDdtDry));
90     dFLDdtDry=dFLDdtDry(tmp1); FLDkkFROMtmp=FLDkkFROM(tmp1);
91     A=A+sparse(LL(FLDkkFROMtmp),LL(FLDkkFROMtmp),dFLDdtDry,nn,nn);
92    
93     end; end; end;
94    
95     %to check results:
96     %figure; spy(A);
97    
98     %4) solve for potential:
99     yy=convert2array(fld); yy=yy(find(KK~=0));
100     xx=A\yy;
101     yyFROMxx=A*xx;
102    
103     %5) prepare output:
104     fldDivPot=0*convert2array(fld); fldDivPot(find(KK~=0))=xx;
105     fldDivPot=convert2array(fldDivPot,fld);
106     [fldUdiv,fldVdiv]=calc_T_grad(fldDivPot,0);
107     %unlike calc_T_grad, we work in grid point index, so we need to omit grid factors
108     fldUdiv=fldUdiv.*mygrid.DXC; fldVdiv=fldVdiv.*mygrid.DYC;
109    
110     %to check the results:
111     %fld1=0*convert2array(fld); fld1(find(KK~=0))=xx;
112     %fld2=0*convert2array(fld); fld2(find(KK~=0))=yyFROMxx;
113     %fld3=convert2array(calc_UV_div(fldU,fldV,{}));%no grid scaling factor in div. or transports
114    
115     1;
116    

  ViewVC Help
Powered by ViewVC 1.1.22