NCCOOS Trac Projects: Top | Web | Platforms | Processing | Viz | Sprints | Sandbox | (Wind)

root/gliderproc/trunk/MATLAB/opnml/FDCONT/genbfd.m

Revision 495 (checked in by cbc, 12 years ago)

Initial import of Stark code.

Line 
1 function bfd=genbfd(fem_grid_struct,xylist,outflag,bfdfilename,refl)
2 %GENBFD generate a "basis function data" file for FD contouring
3 %   GENBFD computes an information file for contouring FEM
4 %   node-based data using FD sampled points and MATLAB's
5 %   contourf routine.  The FD-based plotting tools are part
6 %   of the FDCONT toolkit.
7 %
8 %   Input: fem_grid_struct - FEM domain
9 %          xylist - FD point list (n X 2) or a 1x2 vector
10 %                   containing [nx ny], the number of FD
11 %                   points in (x,y) to discretize the area.
12 %                   See below.
13 %          outflag - flag to output .bfd file to disk
14 %                    if outflag==1, the bfd matrix is output to
15 %                    the current directory with the name
16 %                    <gridname>.bfd.
17 %                    if outflag==0, the bfd matrix is returned
18 %                    workspace.
19 %          bfdfilename - optional filename to write bfd matrix to.
20 %          refl - Reference lon/lat for CPP transformation
21 %                 1x2 vector [reflon reflat]
22 %                 (optional: output will be in input coordinates)
23 %
24 %          Arguments 1-3 are required.
25 %
26 %          If xylist is passed in as [nx ny], GENBFD generates
27 %          the FD points convering an area equal to the
28 %          total extent of the FEM domain.  If only 1 integer
29 %          is passed in, then nx=ny, GENBFD takes the smaller
30 %          of [(xmax-xmin),(ymax-ymin)] for equal spacing.
31 %
32 %   Output: The result of GENBFD is a matrix
33 %   containing the following information.
34 %
35 %   For each FD point:
36 %    x y elem n1 n2 n3 b1 b2 b3 depth
37 %
38 %   where x,y = FD point coordinate
39 %         elem = FE element containing x y (==0 if outside FE mesh)
40 %         n1,n2,n3 = node numbers of containing element (or closest)
41 %         b1,b2,b3 = basis function values (or 1 0 0 if outside FEM)
42 %         depth = depth at xy (or depth of closest node)
43 %
44 %   For any given FD discretization, the bfd matrix need only be
45 %   computed once.  The bfd matrix is passed to FE2FD to perform
46 %   the actual FE to FD interpolation.
47 %
48 %   Call:  bfd=genbfd(fem_grid_struct,xylist,outflag)
49 %     OR   bfd=genbfd(fem_grid_struct,xylist,outflag,bfdfilename)
50 %     OR   bfd=genbfd(fem_grid_struct,[nx ny],outflag,bfdfilename)
51 %     OR   bfd=genbfd(fem_grid_struct,[nx ny],outflag,refl)
52 %     OR   bfd=genbfd(fem_grid_struct,[nx ny],outflag,bfdfilename,refl)
53 %
54 %   Written by: Brian Blanton (Spring 99) to implement
55 %   Chris Naimie's "bfd" file in MATLAB.
56 %
57 %   CPP transformation added 07/08/2003 (CRE)
58 %
59
60 if nargin<3 | nargin>5
61    error('Incorrect number of arguments to GENBFD.')
62 end
63
64 if outflag~=0 & outflag~=1
65    error('outflag to GENBFD must be 0|1.')
66 end
67
68 grid=fem_grid_struct; grid=el_areas(grid);
69 if ~is_valid_struct(fem_grid_struct)
70    error('    Argument to GENBFD must be a valid fem_grid_struct.')
71 end
72 if ~is_valid_struct2(fem_grid_struct)
73    disp('Adding Grid Components')
74    grid=belint(grid);
75    grid=el_areas(grid);
76 end
77
78 if nargin==3
79    bfdfilename=fem_grid_struct.name;
80 end
81 if nargin==4
82    if ~isstr(bfdfilename)
83       if(isa(bfdfilename,'double')&(size(bfdfilename)==[1 2]))
84         refl=bfdfilename;
85         bfdfilename=fem_grid_struct.name;
86         if outflag==0
87           disp('Outflag==0, ignoring bfdfilename input.')
88         end
89       else
90         error('bfdfilename to GENBFD must be a string.')
91       end
92    end
93 end
94
95 if nargin==5
96    if ~isstr(bfdfilename)
97       error('bfdfilename to GENBFD must be a string.')
98    end
99    if outflag==0
100       disp('Outflag=0, ignoring bfdfilename input.')
101    end
102 end
103
104 % Check size of xylist; if it is 1x1|1x2|2x1, assume this is
105 % the [nx ny] case and generate the FD points
106 [m,n]=size(xylist);
107 if m*n==1 | m*n==2
108    if m*n==1
109       nx=xylist;ny=[]; 
110    else
111       nx=xylist(1);ny=xylist(2);
112    end
113    
114    if nx<3 | ny < 3
115       error('[nx,ny] to genbfd must be larger than 3x2 or 2x3')
116    end
117    disp(...
118    ['Generating FD points as [' int2str(nx) ' ' int2str(ny) '] array...'])
119    [xylist,nnx,nny]=gen_fd_points(nx,ny,fem_grid_struct);
120    nx=nnx;ny=nny;
121 else
122    if (n==1 | m==1)&m*n>2
123       error('xylist to BASIS1D must be Nx2')
124    end
125 end
126
127 % allow for possible 2 x N shape
128 if n>2
129    xylist=xylist';
130 end
131
132 [m,n]=size(xylist);
133
134 bfd=NaN*ones(m,10);
135
136 xfd=xylist(:,1);
137 yfd=xylist(:,2);
138 if(exist('refl','var'))
139   [xfd,yfd]=ll2xy(xylist(:,2),xylist(:,1),refl(2),refl(1));
140   [xgrd,ygrd]=ll2xy(grid.y,grid.x,refl(2),refl(1));
141   grid.x=xgrd; grid.y=ygrd; grid=el_areas(grid); grid=belint(grid);
142 end
143 bfd(:,1)=xfd;
144 bfd(:,2)=yfd;
145
146 % Locate elements for xylist
147 disp('Finding elements...')
148 j=findelem(grid,[xfd yfd]);
149
150 % which points are in.out of the FEM domain
151 idx_in_fem=find(~isnan(j));
152 idx_out_fem=find(isnan(j));
153
154 % Fill element column of bfd
155 bfd(idx_in_fem,3)=j(idx_in_fem);
156 bfd(idx_out_fem,3)=zeros(size(idx_out_fem));
157
158 % NODE COLUMNS of bfd
159 bfd(idx_in_fem,4:6)=grid.e(j(idx_in_fem),:);
160 % Find nearest nodes for fd points outside FEM
161 % Only need to search boundary nodes for closest
162 disp('Minimizing distances...')
163 [bnd,cbnd] = count(grid.bnd);
164 xbnd=grid.x(bnd);
165 ybnd=grid.y(bnd);
166 xout=xfd(idx_out_fem);
167 yout=yfd(idx_out_fem);
168 XOUT=xout*ones(size(xbnd'));
169 XBND=ones(size(xout))*xbnd';
170 YOUT=yout*ones(size(ybnd'));
171 YBND=ones(size(yout))*ybnd';
172 XDIF=XOUT-XBND;YDIF=YOUT-YBND;
173 DIST=sqrt(XDIF.*XDIF + YDIF.*YDIF);
174 [min_dist,imin] = min(DIST');
175 nearest_nodes=bnd(imin);
176 nearest_nodes=nearest_nodes(:);
177 bfd(idx_out_fem,4:6)=[nearest_nodes nearest_nodes nearest_nodes];
178
179 % BASIS
180 disp('Computing interp basis...')
181 %size([xfd(idx_in_fem) yfd(idx_in_fem)])
182 phi=basis2d(grid,[xfd(idx_in_fem) yfd(idx_in_fem)],j(idx_in_fem));
183 bfd(idx_in_fem,7:9)=phi;
184
185 %
186 % Check sum of basis;
187 bsum=sum(phi');
188 tol=1e-8;
189 idx=find(bsum>1+tol | bsum<0-tol);
190 if ~isempty(idx)
191    error('Sum of FE basis ~=1.')
192 end
193
194 %
195 bfd(idx_out_fem,7:9)=...
196    [ones(size(nearest_nodes)) zeros(size(nearest_nodes)) zeros(size(nearest_nodes))];
197
198 % DEPTHS
199 disp('Interpolating depths...')
200 bfd(idx_out_fem,10)=grid.z(nearest_nodes);
201 bfd(idx_in_fem,10)=interp_scalar(grid,grid.z,xfd(idx_in_fem),yfd(idx_in_fem),...
202 j(idx_in_fem));
203
204 if ~isempty(find(isnan(bfd(:))))
205    disp('Still NaNs in bfd array')
206 end
207
208 if(exist('refl','var'))
209   bfd(:,1:2)=xylist;
210 end
211
212 delete(findobj(0,'Tag','GENBFD fig'))
213 figure('MenuBar','none','Name','GENBFD Output')
214 line(bfd(:,1),bfd(:,2),'LineStyle','none','Marker','.','Color','r')
215 set(gcf,'Tag','GENBFD fig')
216 title_string=['GENBFD disc. [' int2str(nx) ' ' int2str(ny) '] on ' fem_grid_struct.name];
217 title(title_string)
218 hb=plotbnd(fem_grid_struct);set(hb,'LineWidth',2)
219 axis('tight')
220 drawnow
221
222
223 % Check for output file flag
224 if outflag==1
225    filename=[bfdfilename '.bfd'];
226    disp(['Writing BFD matrix to ' filename])
227    fid=fopen(filename,'w');
228    fprintf(fid,'%.3f %.3f %d %d %d %d %f %f %f %.2f\n',bfd');
229 end
230 if nargout==0
231    bfd=[];
232 end
233
234 %
235 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
236 %%%%% PRIVATE FUNCTION FOR GENBFD  %%%%%%%%%%%%%%%%%%%%%
237 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
238 function [xy,nnx,nny]=gen_fd_points(nx,ny,fem_grid_struct)
239 x=fem_grid_struct.x;
240 y=fem_grid_struct.y;
241
242 xmin=min(x);
243 xmax=max(x);
244 ymin=min(y);
245 ymax=max(y);
246 xrange=xmax-xmin;
247 yrange=ymax-ymin;
248
249 if isempty(ny)
250    minrange=min(xrange,yrange);
251    nnx=nx;
252 else
253    nnx=nx;
254    nny=ny;
255 end
256
257 if isempty(ny)
258    dx=((xmax-xmin)/(nnx-1));
259    xx=xmin:dx:xmax;
260    yy=ymin:dx:ymax;
261    nny=length(yy);
262 else
263    xx=linspace(xmin,xmax,nnx);
264    yy=linspace(ymin,ymax,nny);
265 end
266 [XX,YY]=meshgrid(xx,yy);
267 XX=XX';YY=YY';   %  to get x-coord to vary fastest.
268 xy=[XX(:) YY(:)];
269
270 disp(['DX = ' num2str(xx(2)-xx(1))])
271 disp(['DY = ' num2str(yy(2)-yy(1))])
272
273
274 %
275 %        Brian O. Blanton
276 %        Department of Marine Sciences
277 %        15-1A Venable Hall
278 %        CB# 3300
279 %        Uni. of North Carolina
280 %        Chapel Hill, NC
281 %                 27599-3300
282 %
283 %        919-962-4466
284 %        blanton@marine.unc.edu
285 %
286 %        Spring 1999
287
288
289
290
291
292
293
294
295
Note: See TracBrowser for help on using the browser.