function interp_DIF_struct = interpDIF( DIF_struct_cell ) err_dlgname = 'Error in DIF interpolation'; % Load saved sensitivity factors for building dimensions: if exist('tmp_s_f.mat','file'), load 'tmp_s_f'; end % If saved options are not found, set to default options: if ~exist('s_f','var') err = errordlg('Sensitivity factors for interpolation not defined.', err_dlgname); end s_f = s_f; n_m = length( DIF_struct_cell ); % number of models to interpolate between if n_m<2 err = errordlg(['Results from at least two building models are required for interpolation:' ... 'DIF_struct_array must have length > 1'], err_dlgname); uiwait(err); interp_DIF_struct.error = 1; return; end % Assemble list of fields common to all structures in DIF_struct_cell: fields = fieldnames(DIF_struct_cell{1}); for i=2:n_m fields_i = fieldnames(DIF_struct_cell{i}); fields = intersect(fields,fields_i); end % Create a structure array containing only the common fields: for i=1:n_m for j=1:length(fields) DIF_struct_array(i).(fields{j}) = DIF_struct_cell{i}.(fields{j}); end end % error checking: % make sure DIF_struct_array has length > 1 % make sure building dimensions, terrain, response names, and frame % locations coincide for all models: force_units = DIF_struct_array(1).force_units; length_units = DIF_struct_array(1).length_units; ws_units = DIF_struct_array(1).ws_units; terrain = DIF_struct_array(1).terrain; theta = DIF_struct_array(1).theta; frame_coords = DIF_struct_array(1).frame_coords; attach_pts = DIF_struct_array(1).attach_pts; d0 = DIF_struct_array(1).d0; resp_names = DIF_struct_array(1).resp_names; resp_units = DIF_struct_array(1).resp_units; n_r = length(resp_names); tol = 10^-3; % tolerance for coincidence of dimensions, frame locations, scale factors for i = 1:n_m if ~strcmp(force_units,DIF_struct_array(i).force_units) err = errordlg('The force units must coincide for all models used in interpolation', err_dlgname); uiwait(err); interp_DIF_struct.error = 1; return; elseif ~strcmp(length_units,DIF_struct_array(i).length_units) err = errordlg('The length units must coincide for all models used in interpolation', err_dlgname); uiwait(err); interp_DIF_struct.error = 1; return; elseif ~strcmp(ws_units,DIF_struct_array(i).ws_units) err = errordlg('The wind speed units must coincide for all models used in interpolation', err_dlgname); uiwait(err); interp_DIF_struct.error = 1; return; elseif ~strcmp(terrain,DIF_struct_array(i).terrain) err = errordlg('The terrain conditions must coincide for all models used in interpolation', err_dlgname); uiwait(err); interp_DIF_struct.error = 1; return; elseif length(theta)~=length(DIF_struct_array(i).theta) || any(theta~=DIF_struct_array(i).theta) err = errordlg( 'The wind directions must coincide for all models used in interpolation', err_dlgname); uiwait(err); interp_DIF_struct.error = 1; return; elseif any(size(frame_coords)~=size(DIF_struct_array(i).frame_coords)) || max(max(abs(frame_coords-DIF_struct_array(i).frame_coords)))>tol err = errordlg( 'The frame coordinates must coincide for all models used in interpolation', err_dlgname); uiwait(err); interp_DIF_struct.error = 1; return; elseif any(size(attach_pts)~=size(DIF_struct_array(i).attach_pts)) || max(max(abs(attach_pts-DIF_struct_array(i).attach_pts)))>tol err = errordlg( 'The attachment locations must coincide for all models used in interpolation', err_dlgname); uiwait(err); interp_DIF_struct.error = 1; return; elseif max(max(abs(d0-DIF_struct_array(i).d0)))>tol err = errordlg( 'The building dimensions must coincide for all models used in interpolation',err_dlgname); uiwait(err); interp_DIF_struct.error = 1; return; elseif max(max(abs(d0-DIF_struct_array(i).d)))1 err = errordlg( 'The DIF results used in interpolation must not have been obtained by interpolation themselves.',err_dlgname); uiwait(err); interp_DIF_struct.error = 1; return; else d0_mx(i,:) = DIF_struct_array(i).d0; d(i,:) = DIF_struct_array(i).d; end end interp_DIF_struct.force_units = force_units; interp_DIF_struct.length_units = length_units; interp_DIF_struct.ws_units = ws_units; interp_DIF_struct.terrain = terrain; interp_DIF_struct.theta = theta; interp_DIF_struct.frame_coords = frame_coords; interp_DIF_struct.attach_pts = attach_pts; interp_DIF_struct.d0 = d0; interp_DIF_struct.d = d; % Form matrix of normalized deviations of model dimensions from building dimensions: delta(:,1) = abs(d(:,1)./d0_mx(:,1)-1); % width: W_i/W_0 -1 delta(:,2) = abs((d(:,2)./d(:,1))./(d0_mx(:,2)./d0_mx(:,1))-1); % aspect ratio: (L_i/W_i)/(L_0/W_0)-1 delta(:,3) = abs((d(:,3)./d(:,1))./(d0_mx(:,3)./d0_mx(:,1))-1); % height ratio: (H_i/W_i)/(H_0/W_0)-1 delta(:,4) = abs((d(:,4)./d(:,1))./(d0_mx(:,4)./d0_mx(:,1))-1); % roof slope: (R_i/W_i)/(R_0/W_0)-1 norm_s_f = s_f*4/sum(s_f); % normalized sensitivity factors S = diag(norm_s_f); % diagonal matrix of sensitivity factors % scaled vector deviations of model dimensions from building dimensions: delta_s = delta*S; % norm of scaled deviation: dev = diag(delta_s*delta_s').^.5; gam = sum(dev.^-1)^-1; % constant factor in numerator of weighted average wf = gam./dev; % weighting factors for each model in weighted average interp_DIF_struct.wf = wf; % Identify which quantities are available to interpolate: % initialize boolean values for which quantities to interpolate: intrp.X_max_obs = 1; intrp.X_min_obs = 1; intrp.X_max_est = 1; intrp.X_min_est = 1; intrp.load_max = 1; intrp.load_min = 1; for i = 1:n_m if length(DIF_struct_array(i).resp_names) ~= n_r err = errordlg('The number of response quantities must coincide for all models used in interpolation', err_dlgname); uiwait(err); interp_DIF_struct.error = 1; return; end for j = 1:n_r if ~strcmp(resp_names(j), DIF_struct_array(i).resp_names(j)) err = errordlg('The response names must coincide for all models used in interpolation', err_dlgname); uiwait(err); interp_DIF_struct.error = 1; return; elseif ~strcmp(resp_units(j), DIF_struct_array(i).resp_units(j)) err = errordlg('The response units must coincide for all models used in interpolation', err_dlgname); uiwait(err); interp_DIF_struct.error = 1; return; end end if ~isfield(DIF_struct_array, 'X_max_obs') || isempty(DIF_struct_array(i).X_max_obs) intrp.X_max_obs = 0; elseif intrp.X_max_obs==1 if exist('X_max_obs','var') if any(size(X_max_obs)~=size(DIF_struct_array(i).X_max_obs)) err = errordlg('Mismatch in dimensions of the field ''X_max_obs''.', err_dlgname ); uiwait(err); interp_DIF_struct.error =1; return; end else X_max_obs = zeros(size(DIF_struct_array(i).X_max_obs)); X_max_obs_bnd = []; end end if ~isfield(DIF_struct_array, 'X_min_obs') || isempty(DIF_struct_array(i).X_min_obs) intrp.X_min_obs = 0; elseif intrp.X_min_obs==1 if exist('X_min_obs','var') if any(size(X_min_obs)~=size(DIF_struct_array(i).X_min_obs)) err = errordlg('Mismatch in dimensions of the field ''X_min_obs''.', err_dlgname ); uiwait(err); interp_DIF_struct.error =1; return; end else X_min_obs = zeros(size(DIF_struct_array(i).X_min_obs)); X_min_obs_bnd = []; end end if ~isfield(DIF_struct_array, 'X_max_est') || isempty(DIF_struct_array(i).X_max_est) intrp.X_max_est = 0; elseif intrp.X_max_est==1 if exist('X_max_est','var') if any(size(X_max_est)~=size(DIF_struct_array(i).X_max_est)) err = errordlg('Mismatch in dimensions of the field ''X_max_est''.', err_dlgname ); uiwait(err); interp_DIF_struct.error =1; return; end else X_max_est = zeros(size(DIF_struct_array(i).X_max_est)); X_max_est_bnd = []; end end if ~isfield(DIF_struct_array, 'X_min_est') || isempty(DIF_struct_array(i).X_min_est) intrp.X_min_est = 0; elseif intrp.X_min_est==1 if exist('X_min_est','var') if any(size(X_min_est)~=size(DIF_struct_array(i).X_min_est)) err = errordlg('Mismatch in dimensions of the field ''X_min_est''.', err_dlgname ); uiwait(err); interp_DIF_struct.error =1; return; end else X_min_est = zeros(size(DIF_struct_array(i).X_min_est)); X_min_est_bnd = []; end end if ~isfield(DIF_struct_array, 'load_max') || isempty(DIF_struct_array(i).load_max) intrp.load_max = 0; elseif intrp.load_max==1 if exist('load_max','var') if any(size(load_max)~=size(DIF_struct_array(i).load_max)) err = errordlg('Mismatch in dimensions of the field ''load_max''.', err_dlgname ); uiwait(err); interp_DIF_struct.error =1; return; end else load_max = zeros(size(DIF_struct_array(i).load_max)); load_max_bnd = []; end end if ~isfield(DIF_struct_array, 'load_min') || isempty(DIF_struct_array(i).load_min) intrp.load_min = 0; elseif intrp.load_min==1 if exist('load_min','var') if any(size(load_min)~=size(DIF_struct_array(i).load_min)) err = errordlg('Mismatch in dimensions of the field ''load_min''.', err_dlgname ); uiwait(err); interp_DIF_struct.error =1; return; end else load_min = zeros(size(DIF_struct_array(i).load_min)); load_min_bnd = []; end end end interp_DIF_struct.resp_names = DIF_struct_array(1).resp_names; interp_DIF_struct.resp_units = DIF_struct_array(1).resp_units; % Perform the interpolation: for i = 1:n_m if intrp.X_max_obs ==1 X_max_obs = X_max_obs + DIF_struct_array(i).X_max_obs*wf(i); X_max_obs_bnd = cat(2,X_max_obs_bnd,DIF_struct_array(i).X_max_obs); end if intrp.X_min_obs ==1 X_min_obs = X_min_obs + DIF_struct_array(i).X_min_obs*wf(i); X_min_obs_bnd = cat(2,X_min_obs_bnd,DIF_struct_array(i).X_min_obs); end if intrp.X_max_est ==1 X_max_est = X_max_est + DIF_struct_array(i).X_max_est*wf(i); X_max_est_bnd = cat(2,X_max_est_bnd,DIF_struct_array(i).X_max_est); end if intrp.X_min_est ==1 X_min_est = X_min_est + DIF_struct_array(i).X_min_est*wf(i); X_min_est_bnd = cat(2,X_min_est_bnd,DIF_struct_array(i).X_min_est); end if intrp.load_max ==1 load_max = load_max + DIF_struct_array(i).load_max*wf(i); load_max_bnd = cat(3,load_max_bnd,DIF_struct_array(i).load_max); end if intrp.load_min ==1 load_min = load_min + DIF_struct_array(i).load_min*wf(i); load_min_bnd = cat(3,load_min_bnd,DIF_struct_array(i).load_min); end end % Assemble the results in a data structure: if intrp.X_max_obs ==1 interp_DIF_struct.X_max_obs = X_max_obs; interp_DIF_struct.X_max_obs_bnd = X_max_obs_bnd; end if intrp.X_min_obs ==1 interp_DIF_struct.X_min_obs = X_min_obs; interp_DIF_struct.X_min_obs_bnd = X_min_obs_bnd; end if intrp.X_max_est ==1 interp_DIF_struct.X_max_est = X_max_est; interp_DIF_struct.X_max_est_bnd = X_max_est_bnd; end if intrp.X_min_est ==1 interp_DIF_struct.X_min_est = X_min_est; interp_DIF_struct.X_min_est_bnd = X_min_est_bnd; end if intrp.load_max ==1 interp_DIF_struct.load_max = load_max; interp_DIF_struct.load_max_bnd = load_max_bnd; end if intrp.load_min ==1 interp_DIF_struct.load_min = load_min; interp_DIF_struct.load_min_bnd = load_min_bnd; end