% %function: netcdf_ecco_GenericgridMatFirstStep %object: compute the additional information to use an "ECCO format" data set with a non latlon grid %author: Gael Forget (gforget@mit.edu) %date: June 12th, 2007 % %inputs: % - an "ECCO format" data set and grid files (profilesXCincl1PointOverlap* etc) % that the model should generate when you first try to run pkg/profiles % with a non latlon grid % - directories for I/O % - lat_polar (see below) %output: mat files that are then fed to netcdf_ecco_GenericgridMat2Nc (step 2) % %lat_polar: positive value smaller than 90 % [in Cube Sphere/Polar Cap case] % lat_polar should be set to the latitude beyond which lies the cube polar tiles (all of the tile grid points) % -> there we start by project coordinates on the polar tangent plane because the lat/lon system collapes at the pole % -> we refer to this operation as "polar switch" below % [in other grids that do not include the poles] % set it to 85 % %rk: below you will find a parameter [choice_plot] do do some display % function []=netcdf_ecco_GenericgridMatFirstStep_4points(file_data,rep_data,rep_grid,rep_out,lat_polar); warning off MATLAB:mir_warning_variable_used_as_function; fprintf('\n WARNING from netcdf_ecco_GenericgridMatFirstStep.m : \n'); fprintf('please have a look at netcdf_ecco_GenericgridNOTEONOVERLAPCORNERS \n\n'); %choice to do some visual chek or not choice_plot=0; if choice_plot==1; figure; end; fprintf('visualization off \n\n'); %longitude systems: 1 <-> degree east from Greenwich [0 360] // 2 <-> degree east and west [-180 180] lonSystModel=2; if lonSystModel==1; fprintf('the script below assumes [-180 +180] longitudes => please do not change \n'); return; end %-> both model and observations will first be switched to this system eval(['ncload ' rep_data file_data ' prof_lon prof_lat;']); %set the longitude system for observations: [prof_lon]=netcdf_ecco_GenericgridRotateLon(prof_lon,0,0,lonSystModel); prof_lonM2=prof_lon; prof_latM2=prof_lat; list_subsets=[1:4]; for subset_cur=list_subsets switch subset_cur case 1 switch_to_polar=0; list_profilesM2=find((prof_lonM2>=-90&prof_lonM2<90)&abs(prof_latM2)=90)&abs(prof_latM2)=switch_to_polar*lat_polar); suff_cur='northpole'; fprintf('computing high latitude, northern hemisphere \n'); case 4 switch_to_polar=-1; list_profilesM2=find(prof_latM2<=switch_to_polar*lat_polar); suff_cur='southpole'; fprintf('computing high latitude, southern hemisphere \n'); end prof_lonM1=prof_lonM2(list_profilesM2); prof_latM1=prof_latM2(list_profilesM2); %do the "polar switch" for the data [prof_lonM1,prof_latM1]=netcdf_ecco_GenericgridPolarPlaneCoords(prof_lonM1,prof_latM1,switch_to_polar); eval(['files_list=ls('' -1 ' rep_grid 'profilesXC*.data '');']); tmp1=files_list; tmp2=strfind(files_list,rep_grid)+length(rep_grid); tmp3=strfind(files_list,'.data')+4; files_list=''; for tmp4=1:length(tmp2); files_list=strvcat(files_list, tmp1(tmp2(tmp4):tmp3(tmp4)) ); end for tcur=1:size(files_list,1) prof_interp_XC11=NaN*zeros(length(prof_lonM2),1); prof_interp_YC11=prof_interp_XC11; prof_interp_XCNINJ=prof_interp_XC11; prof_interp_YCNINJ=prof_interp_XC11; prof_interp_i=NaN*zeros(length(prof_lonM2),4); prof_interp_j=prof_interp_i; prof_interp_weights=prof_interp_i; prof_interp_lon=prof_interp_i; prof_interp_lat=prof_interp_i; file_cur=deblank(files_list(tcur,:)); tmp3=strfind(file_cur,'.'); ni=str2num(file_cur(tmp3(end-2)+1:tmp3(end-1)-1)); nj=str2num(file_cur(tmp3(end-1)+1:tmp3(end)-1)); fid=fopen([rep_grid file_cur],'r','b'); XC_cur=fread(fid,[ni+2 nj+2],'float64'); fclose(fid); tmp3=strfind(file_cur,'XC'); file_cur(tmp3)='Y'; fid=fopen([rep_grid file_cur],'r','b'); YC_cur=fread(fid,[ni+2 nj+2],'float64'); fclose(fid); XC_ref=XC_cur; YC_ref=YC_cur; %set the longitude system for model: [XC_cur(:)]=netcdf_ecco_GenericgridRotateLon(XC_cur(:),0,0,lonSystModel); %tests to avoid bug particualr cases (test1&test2) and useless loops %------------------------------------------------------------------- %test1=1; if we are to do "polar switch", only tiles that have grid points in the "polar region" can be relevant! test1=1; if switch_to_polar~=0; test1=~isempty(find(( YC_cur(:)-switch_to_polar*(lat_polar-10) )*switch_to_polar > 0)); end; %test2: if no switch_to_polar do not address the polar tiles (the ones that go though all latitudes) test2=1; if switch_to_polar==0; test2=isempty(find(XC_cur(:)>175))|isempty(find(XC_cur(:)<-175))|isempty(find(abs(XC_cur(:))<5)); end; %alternative: % test2=1; if switch_to_polar==0; test2=isempty(find(abs(XC_cur(:)+135)<30))|isempty(find(abs(XC_cur(:)+45)<30))|... % isempty(find(abs(XC_cur(:)-135)<30))|isempty(find(abs(XC_cur(:)-45)<30)); end; %test3: if no data don't bother! test3=~isempty(list_profilesM2); %fprintf([num2str([subset_cur tcur test1 test2 test3]) '\n']); %%%%%%%%%%%%%%%%%%%% if test1&test2&test3 %%%%%%%%%%%%%%%%%%%% if choice_plot==1; subplot(2,1,1); plot(XC_cur(:),YC_cur(:),'yx'); hold on; plot(XC_cur(1,1),YC_cur(1,1),'b.'); plot(XC_cur(end,1),YC_cur(end,1),'m.'); tmp_lonM1=prof_lonM2(list_profilesM2); tmp_latM1=prof_latM2(list_profilesM2); plot(tmp_lonM1,tmp_latM1,'go'); axis([-180 180 -90 90]); end; if switch_to_polar~=0; %switch to polar plane coordinates tmp1=find(( YC_cur(:)-switch_to_polar*(lat_polar-10) )*switch_to_polar <= 0); XC_cur(tmp1)=NaN; YC_cur(tmp1)=NaN; [XC_cur,YC_cur]=netcdf_ecco_GenericgridPolarPlaneCoords(XC_cur,YC_cur,switch_to_polar); [XC_cur,YC_cur]=netcdf_ecco_GenericgridFixFieldsOverlapCorners(XC_cur,YC_cur); else lon0global=0; if ~isempty(find(abs(XC_cur(:))>175)); lon0tile=180; else; lon0tile=0; end; %alternative: lon0tile=mean(XC_cur(:)); prof_lonM1ref=prof_lonM1; %do the "model flip" for the data ... or not [prof_lonM1]=netcdf_ecco_GenericgridRotateLon(prof_lonM1,lon0global,lon0tile,lonSystModel); %do the "model flip" for the model ... or not [XC_cur]=netcdf_ecco_GenericgridRotateLon(XC_cur,lon0global,lon0tile,lonSystModel); [XC_cur,YC_cur]=netcdf_ecco_GenericgridFixFieldsOverlapCorners(XC_cur,YC_cur); end if choice_plot==1; subplot(2,1,2); plot(XC_cur(:),YC_cur(:),'yx'); hold on; plot(XC_cur(1,1),YC_cur(1,1),'b.'); plot(XC_cur(end,1),YC_cur(end,1),'m.'); plot(prof_lonM1,prof_latM1,'go'); if ~switch_to_polar; axis([-180 180 -90 90]); else; axis([-90 90 -90 90]); end; end; x0=zeros((ni+1)*(nj+1),4); y0=x0; i0=x0; j0=x0; tmp_count=0; for icur=1:ni+1; for jcur=1:nj+1; tmp_count=tmp_count+1; x0(tmp_count,:)=[XC_cur(icur,jcur) XC_cur(icur+1,jcur) XC_cur(icur+1,jcur+1) XC_cur(icur,jcur+1)]; y0(tmp_count,:)=[YC_cur(icur,jcur) YC_cur(icur+1,jcur) YC_cur(icur+1,jcur+1) YC_cur(icur,jcur+1)]; i0(tmp_count,:)=[icur icur+1 icur+1 icur]; j0(tmp_count,:)=[jcur jcur jcur+1 jcur+1]; end; end; tmp1=find(~isnan(sum(x0,2))); x0=x0(tmp1,:); y0=y0(tmp1,:); i0=i0(tmp1,:); j0=j0(tmp1,:); %first step: restrict our attention to profiles that are within the area %----------- %will work in any case when % 1) the cell is non polar, so we do not cross the longitude limit % or % 2) we use polar coordinates, which is well defined, for both model and data %=> if this is not the case: I have put some NaNs in XC_cur if isempty(find(isnan(XC_cur))) x00=[XC_cur(:,1)' XC_cur(end,2:end-1) flipdim(XC_cur(:,end)',2) XC_cur(1,end-1:-1:2)]; y00=[YC_cur(:,1)' YC_cur(end,2:end-1) flipdim(YC_cur(:,end)',2) YC_cur(1,end-1:-1:2)]; list_profilesM1=zeros(size(prof_lonM1)); length_div=1e3; num_div=ceil(length(prof_lonM1)/length_div); for cur_div=1:num_div list_profiles0=[(cur_div-1)*length_div+1:min(cur_div*length_div,length(prof_lonM1))]; [tmp1]=netcdf_ecco_GenericgridLocateCell(x00,y00,prof_lonM1(list_profiles0),prof_latM1(list_profiles0)); list_profilesM1(list_profiles0(find(tmp1>0)))=1; end list_profilesM1=find(list_profilesM1>0); prof_lon=prof_lonM1(list_profilesM1); prof_lat=prof_latM1(list_profilesM1); else list_profilesM1=[1:length(prof_lonM1)]'; prof_lon=prof_lonM1; prof_lat=prof_latM1; end %second step: the main computation %--------------------------------- if ~isempty(list_profilesM1) length_div=1e2; num_div=ceil(length(prof_lon)/length_div); for cur_div=1:num_div list_profiles0=[(cur_div-1)*length_div+1:min(cur_div*length_div,length(prof_lon))]; %if mod(cur_div,20)==1; %tmp1=length(find(~isnan(prof_interp_i(:,1)))); tmp2=length(prof_lon); %fprintf([num2str(tcur) ' -- ' num2str(list_profiles0(1)) ' / ' num2str(length(prof_lon)) ' -- ' num2str(tmp1) '\n']); %end [list_profiles2]=netcdf_ecco_GenericgridLocateCell(x0,y0,prof_lon(list_profiles0),prof_lat(list_profiles0)); [coeffs2]=netcdf_ecco_GenericgridCoeffs_4points(x0,y0,prof_lon(list_profiles0),prof_lat(list_profiles0)); list_profiles3=find(sum(list_profiles2,2)>0); for kkcur=1:length(list_profiles3) %index in small data vector: kcur0=list_profiles3(kkcur); %more than one 1 can happen when close to cell edges; we pick the first; tmp1=find(list_profiles2(kcur0,:)>0); tmp1=tmp1(1); tmp2=squeeze(coeffs2(kcur0,tmp1,:)); %NOT PRACTICAL tmp3=find(tmp2>0); %index in the full data vector: kcur=list_profilesM2(list_profilesM1(list_profiles0(kcur0))); %fill arrays: prof_interp_XC11(kcur)=XC_ref(2,2); prof_interp_YC11(kcur)=YC_ref(2,2); prof_interp_XCNINJ(kcur)=XC_ref(end-1,end-1); prof_interp_YCNINJ(kcur)=YC_ref(end-1,end-1); prof_interp_i(kcur,:)=i0(tmp1,:)-1; prof_interp_j(kcur,:)=j0(tmp1,:)-1; prof_interp_weights(kcur,:)=tmp2(:); end end%for cur_div=1:num_div end%if ~isempty(list_profilesM1) if switch_to_polar==0; %undo the "model flip" for the data [prof_lonM1]=netcdf_ecco_GenericgridRotateLon(prof_lonM1,lon0tile,lon0global,lonSystModel); %needed for computation [XC_cur]=netcdf_ecco_GenericgridRotateLon(XC_cur,lon0tile,lon0global,lonSystModel); %needed for plot only % if ~isempty(find(mod(prof_lonM1,360)~=mod(prof_lonM1ref,360))); % fprintf('pb due to change in longitudes => stop \n'); return; % end end if choice_plot==1; tmp1=find(~isnan(prof_interp_i(:,1))); tmp_i=prof_interp_i(tmp1,1); tmp_j=prof_interp_j(tmp1,1); tmp2=(tmp_j+1-1)*(ni+2)+(tmp_i+1); plot(XC_cur(tmp2),YC_cur(tmp2),'ro'); % tmp_i=prof_interp_i(tmp1,2); tmp_j=prof_interp_j(tmp1,2); tmp2=(tmp_j+1-1)*(ni+2)+(tmp_i+1); plot(XC_cur(tmp2),YC_cur(tmp2),'bo'); if ~switch_to_polar; plot(prof_lonM2(tmp1),prof_latM2(tmp1),'k.'); else; tmp_x=prof_lonM2(tmp1); tmp_y=prof_latM2(tmp1); [tmp_x,tmp_y]=netcdf_ecco_GenericgridPolarPlaneCoords(tmp_x,tmp_y,switch_to_polar); plot(tmp_x,tmp_y,'k.'); end; pause(2); clf; end; %third step : we do not use overlap corner points in interpolation %----------- % %rare cases when netcdf_ecco_GenericgridCoeffs_4points collapses on "corrected corners": %tmp1=find(~isnan(prof_interp_XC11)&sum(prof_interp_weights,2)~=1); tmp1=find(~isnan(prof_interp_XC11)&round(sum(prof_interp_weights,2)*1e6)*1e-6~=1); tmp2=( (prof_interp_i(tmp1,:)==0&prof_interp_j(tmp1,:)==0)|( prof_interp_i(tmp1,:)==0&prof_interp_j(tmp1,:)==nj+1 )|... ( prof_interp_i(tmp1,:)==ni+1&prof_interp_j(tmp1,:)==0 )|( prof_interp_i(tmp1,:)==ni+1&prof_interp_j(tmp1,:)==nj+1 )); if ~isempty(find(sum(tmp2,2)~=1)); fprintf('this is unexpected!! \n'); return; end; % -> equally weighted average of the three neighbors tmp3=prof_interp_weights(tmp1,:); tmp3(find(tmp2==0))=1/3; tmp3(find(tmp2==1))=0; prof_interp_weights(tmp1,:)=tmp3; %other cases: tmp1=find(~isnan(prof_interp_XC11)); tmp2=( (prof_interp_i(tmp1,:)==0&prof_interp_j(tmp1,:)==0)|( prof_interp_i(tmp1,:)==0&prof_interp_j(tmp1,:)==nj+1 )|... ( prof_interp_i(tmp1,:)==ni+1&prof_interp_j(tmp1,:)==0 )|( prof_interp_i(tmp1,:)==ni+1&prof_interp_j(tmp1,:)==nj+1 )); tmp3=find(sum(tmp2,2)==1); tmp1=tmp1(tmp3); tmp2=tmp2(tmp3,:); % -> distribute equally the corner weight to the three neighbors tmp3=prof_interp_weights(tmp1,:); if ~isempty(find(tmp2.*tmp3~=0)); fprintf('o'); tmp3=tmp3+1/3*sum(tmp3.*tmp2,2)*ones(1,4); tmp3(find(tmp2==1))=0; prof_interp_weights(tmp1,:)=tmp3; end %fourth step: store the lon/lat of the interpolation points for checks %------------ tmp1=find(~isnan(prof_interp_i)); tmp2=(ni+2)*prof_interp_j(tmp1)+prof_interp_i(tmp1)+1; %rk: the computation of the previous line accounts for the fact that i/j go from 0 to ni+1/nj+1 prof_interp_lon(tmp1)=XC_ref(tmp2); prof_interp_lat(tmp1)=YC_ref(tmp2); %fifth step: save in .mat file %------------------------------ tmp1=findstr(file_data,'.nc'); eval(['save ' rep_out file_data(1:tmp1(end)-1) '_4mygrid.' suff_cur '.' num2str(tcur) '.mat prof_interp_*;']); %%%%%%%%%%%%%%%%%%%%%%%% end%if test1&test2&test3 %%%%%%%%%%%%%%%%%%%%%%%% end%for tcur=... end%for subset_cur=1:3