diff --git a/monte_carlo_Pr_dBm_rev2_app.m b/monte_carlo_Pr_dBm_rev2_app.m new file mode 100644 index 0000000..468aaad --- /dev/null +++ b/monte_carlo_Pr_dBm_rev2_app.m @@ -0,0 +1,72 @@ +function [monte_carlo_pr_dBm]=monte_carlo_Pr_dBm_rev2_app(app,reliability_range,cut_temp_Pr_dBm,rand_numbers) +%MONTE_CARLO_PR_DBM_REV2_APP RNG-free Monte Carlo PR interpolation. +% rand_numbers are precomputed reliabilities (num_tx x 1). + +[num_tx,~]=size(cut_temp_Pr_dBm); + +[reliability_range,sort_idx]=sort(reliability_range); +cut_temp_Pr_dBm=cut_temp_Pr_dBm(:,sort_idx); + +monte_carlo_pr_dBm=NaN(num_tx,1); +rel_min=min(reliability_range); +rel_max=max(reliability_range); + +if rel_min==rel_max + monte_carlo_pr_dBm=cut_temp_Pr_dBm(:,1); +else + rand_numbers=min(max(rand_numbers(:),rel_min),rel_max); + + [ind_prev]=nearestpoint_app(app,rand_numbers,reliability_range,'previous'); + [ind_next]=nearestpoint_app(app,rand_numbers,reliability_range,'next'); + + idx_nan_prev=find(isnan(ind_prev)==1); + if ~isempty(idx_nan_prev) + ind_prev(idx_nan_prev)=1; + end + + idx_nan_next=find(isnan(ind_next)==1); + if ~isempty(idx_nan_next) + ind_next(idx_nan_next)=length(reliability_range); + end + + remainder=rand_numbers-reliability_range(ind_prev); + span=reliability_range(ind_next)-reliability_range(ind_prev); + + for tx_idx=1:1:num_tx + temp_diff_Pr=cut_temp_Pr_dBm(tx_idx,ind_prev(tx_idx))-cut_temp_Pr_dBm(tx_idx,ind_next(tx_idx)); + subtract_Pr=(temp_diff_Pr.*(remainder(tx_idx)./span(tx_idx))); + if isnan(subtract_Pr) + subtract_Pr=0; + end + monte_carlo_pr_dBm(tx_idx)=cut_temp_Pr_dBm(tx_idx,ind_prev(tx_idx))-subtract_Pr; + end +end + +if any(monte_carlo_pr_dBm + 'Error: MC too small'; %#ok + pause; +end + +if any(monte_carlo_pr_dBm>cut_temp_Pr_dBm(:,1)) + horzcat(monte_carlo_pr_dBm,cut_temp_Pr_dBm(:,1),cut_temp_Pr_dBm(:,end),monte_carlo_pr_dBm>cut_temp_Pr_dBm(:,1)); %#ok + 'Error: MC too large'; %#ok + pause; +end + +if any(isnan(monte_carlo_pr_dBm)) + 'NaN Error with monte_carlo_pr_dBm'; %#ok + pause; +end + +if any(monte_carlo_pr_dBm==0) + 'Zero Error with monte_carlo_pr_dBm'; %#ok + pause; +end + +if any(isinf(monte_carlo_pr_dBm)) + inf_idx=find(isinf(monte_carlo_pr_dBm)); + monte_carlo_pr_dBm(inf_idx)=-1; +end + +end diff --git a/monte_carlo_clutter_rev3_app.m b/monte_carlo_clutter_rev3_app.m new file mode 100644 index 0000000..0443972 --- /dev/null +++ b/monte_carlo_clutter_rev3_app.m @@ -0,0 +1,54 @@ +function [monte_carlo_clutter_loss]=monte_carlo_clutter_rev3_app(app,reliability_range,sort_clutter_loss,rand_numbers) +%MONTE_CARLO_CLUTTER_REV3_APP RNG-free Monte Carlo clutter interpolation. + +[num_tx,~]=size(sort_clutter_loss); + +[reliability_range,sort_idx]=sort(reliability_range); +sort_clutter_loss=sort_clutter_loss(:,sort_idx); + +monte_carlo_clutter_loss=NaN(num_tx,1); +rel_min=min(reliability_range); +rel_max=max(reliability_range); + +if rel_min==rel_max + monte_carlo_clutter_loss=sort_clutter_loss(:,1); +else + rand_numbers=min(max(rand_numbers(:),rel_min),rel_max); + + [ind_prev]=nearestpoint_app(app,rand_numbers,reliability_range,'previous'); + [ind_next]=nearestpoint_app(app,rand_numbers,reliability_range,'next'); + + idx_nan_prev=find(isnan(ind_prev)==1); + if ~isempty(idx_nan_prev) + ind_prev(idx_nan_prev)=1; + end + + idx_nan_next=find(isnan(ind_next)==1); + if ~isempty(idx_nan_next) + ind_next(idx_nan_next)=length(reliability_range); + end + + remainder=rand_numbers-reliability_range(ind_prev); + span=reliability_range(ind_next)-reliability_range(ind_prev); + + for tx_idx=1:1:num_tx + temp_diff_Pr=sort_clutter_loss(tx_idx,ind_prev(tx_idx))-sort_clutter_loss(tx_idx,ind_next(tx_idx)); + subtract_Pr=(temp_diff_Pr.*(remainder(tx_idx)./span(tx_idx))); + if isnan(subtract_Pr) + subtract_Pr=0; + end + monte_carlo_clutter_loss(tx_idx)=sort_clutter_loss(tx_idx,ind_prev(tx_idx))-subtract_Pr; + end +end + +if any(isnan(monte_carlo_clutter_loss)) + 'NaN Error with monte_carlo_pr_dBm'; %#ok + pause; +end + +if any(isinf(monte_carlo_clutter_loss)) + inf_idx=find(isinf(monte_carlo_clutter_loss)); + monte_carlo_clutter_loss(inf_idx)=0; +end + +end diff --git a/monte_carlo_super_bs_eirp_dist_rev5.m b/monte_carlo_super_bs_eirp_dist_rev5.m new file mode 100644 index 0000000..c494198 --- /dev/null +++ b/monte_carlo_super_bs_eirp_dist_rev5.m @@ -0,0 +1,22 @@ +function [rand_norm_eirp]=monte_carlo_super_bs_eirp_dist_rev5(app,super_array_bs_eirp_dist,reliability,rand_numbers) +%MONTE_CARLO_SUPER_BS_EIRP_DIST_REV5 RNG-free MC EIRP interpolation. + +[num_rows,num_cols]=size(super_array_bs_eirp_dist); %#ok + +if num_cols>1 + [reliability,sort_idx]=sort(reliability(:).'); + super_array_bs_eirp_dist=super_array_bs_eirp_dist(:,sort_idx); + + rel_min=min(reliability); + rel_max=max(reliability); + rand_numbers=min(max(rand_numbers(:),rel_min),rel_max); + + rand_norm_eirp=NaN(num_rows,1); + for n=1:1:num_rows + rand_norm_eirp(n)=interp1(reliability,super_array_bs_eirp_dist(n,:),rand_numbers(n),'spline'); + end +else + rand_norm_eirp=zeros(num_rows,1); +end + +end diff --git a/subchunk_agg_check_rev8.m b/subchunk_agg_check_rev8.m new file mode 100644 index 0000000..74b2caa --- /dev/null +++ b/subchunk_agg_check_rev8.m @@ -0,0 +1,119 @@ +function [sub_array_agg_check_mc_dBm]=subchunk_agg_check_rev8(app,cell_aas_dist_data,array_bs_azi_data,radar_beamwidth,min_azimuth,max_azimuth,base_protection_pts,point_idx,on_list_bs,cell_sim_chuck_idx,rand_seed1,agg_check_reliability,on_full_Pr_dBm,clutter_loss,custom_antenna_pattern,sub_point_idx) + +%%%%%%%%%Adding clutter distribution in monte carlo later +%%%%%%%%%%We just have to make a new bs_eirp_dist based on the azimuth +%%%%%%%%%%of the base station antenna offset to the federal point. +array_aas_dist_data=cell_aas_dist_data{2}; +aas_dist_azimuth=cell_aas_dist_data{1}; +mod_azi_diff_bs=array_bs_azi_data(:,4); + +%%%%%%%%%Find the azimuth off-axis antenna loss +[nn_azi_idx]=nearestpoint_app(app,mod_azi_diff_bs,aas_dist_azimuth); %%%%%%%Nearest Azimuth Idx +super_array_bs_eirp_dist=array_aas_dist_data(nn_azi_idx, :); + +%%%%%%%%%%%%%%%%Calculate the simualation azimuths +[array_sim_azimuth,num_sim_azi]=calc_sim_azimuths_rev3_360_azimuths_app(app,radar_beamwidth,min_azimuth,max_azimuth); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Calculate Each Base Station Azimuth +sim_pt=base_protection_pts(point_idx,:); +bs_azimuth=azimuth(sim_pt(1),sim_pt(2),on_list_bs(:,1),on_list_bs(:,2)); + +%%%%%%%%%%%%%%Generate MC Iterations and Calculate Move List +sub_mc_idx=cell_sim_chuck_idx{sub_point_idx}; +num_mc_idx=length(sub_mc_idx); +num_bs=length(bs_azimuth); +sub_array_agg_check_mc_dBm=NaN(num_mc_idx,num_sim_azi); + +% ------------------------------------------------------------------------- +% STEP 1: Deterministic MC random precompute (seed identity preserved) +% rand_*_all dimensions: [num_bs x num_mc_idx] +% ------------------------------------------------------------------------- +rel_min=min(agg_check_reliability); +rel_max=max(agg_check_reliability); + +if rel_min==rel_max + rand_pr_all=repmat(rel_min,num_bs,num_mc_idx); + rand_eirp_all=rand_pr_all; + rand_clutter_all=rand_pr_all; +else + rand_pr_all=NaN(num_bs,num_mc_idx); + rand_eirp_all=NaN(num_bs,num_mc_idx); + rand_clutter_all=NaN(num_bs,num_mc_idx); + + for loop_idx=1:1:num_mc_idx + mc_iter=sub_mc_idx(loop_idx); + + rng(rand_seed1+mc_iter); % PR draw identity + rand_pr_all(:,loop_idx)=rand(num_bs,1)*(rel_max-rel_min)+rel_min; + + rng(rand_seed1+mc_iter+1); % EIRP draw identity + rand_eirp_all(:,loop_idx)=rand(num_bs,1)*(rel_max-rel_min)+rel_min; + + rng(rand_seed1+mc_iter+2); % Clutter draw identity + rand_clutter_all(:,loop_idx)=rand(num_bs,1)*(rel_max-rel_min)+rel_min; + end +end + +% ------------------------------------------------------------------------- +% STEP 2: Precompute off-axis gain matrix once for all (bs,sim_azimuth) +% off_axis_gain_matrix dimensions: [num_bs x num_sim_azi] +% Nearest-neighbor behavior mirrors rev7 path. +% ------------------------------------------------------------------------- +[n_pat_rows,~]=size(custom_antenna_pattern); +pat_az=mod(custom_antenna_pattern(:,1),360); +pat_gain=custom_antenna_pattern(:,2); + +[pat_az_unique,ia_unique]=unique(pat_az,'stable'); +pat_gain_unique=pat_gain(ia_unique); + +off_axis_gain_matrix=NaN(num_bs,num_sim_azi); +for azimuth_idx=1:1:num_sim_azi + sim_azimuth=array_sim_azimuth(azimuth_idx); + rel_az=mod(bs_azimuth-sim_azimuth,360); + ant_deg_idx=nearestpoint_app(app,rel_az,pat_az_unique); + off_axis_gain_matrix(:,azimuth_idx)=pat_gain_unique(ant_deg_idx); +end + +% ------------------------------------------------------------------------- +% STEP 3/4: Compute MC terms with RNG-free rev helpers. +% ------------------------------------------------------------------------- +sort_monte_carlo_pr_dBm_all=NaN(num_bs,num_mc_idx); +for loop_idx=1:1:num_mc_idx + pre_sort_monte_carlo_pr_dBm=monte_carlo_Pr_dBm_rev2_app(app,agg_check_reliability,on_full_Pr_dBm,rand_pr_all(:,loop_idx)); + rand_norm_eirp=monte_carlo_super_bs_eirp_dist_rev5(app,super_array_bs_eirp_dist,agg_check_reliability,rand_eirp_all(:,loop_idx)); + monte_carlo_clutter_loss=monte_carlo_clutter_rev3_app(app,agg_check_reliability,clutter_loss,rand_clutter_all(:,loop_idx)); + + sort_monte_carlo_pr_dBm_all(:,loop_idx)=pre_sort_monte_carlo_pr_dBm+rand_norm_eirp-monte_carlo_clutter_loss; +end + +% ------------------------------------------------------------------------- +% STEP 5: Aggregate across azimuth in vectorized chunks (no inner azimuth loop) +% ------------------------------------------------------------------------- +azi_chunk=128; +for loop_idx=1:1:num_mc_idx + base_mc=sort_monte_carlo_pr_dBm_all(:,loop_idx); + + azimuth_agg_dBm=NaN(1,num_sim_azi); + for azi_start=1:azi_chunk:num_sim_azi + azi_end=min(azi_start+azi_chunk-1,num_sim_azi); + chunk_gain=off_axis_gain_matrix(:,azi_start:azi_end); + sort_temp_mc_dBm=base_mc+chunk_gain; + + if any(isnan(sort_temp_mc_dBm),'all') + disp_progress(app,strcat('ERROR PAUSE: Inside Agg Check: NaN Error: sort_temp_mc_dBm')) + pause; + end + + binary_sort_mc_watts=db2pow(sort_temp_mc_dBm)/1000; + if any(isnan(binary_sort_mc_watts),'all') + disp_progress(app,strcat('ERROR PAUSE: Inside Agg Check Rev8: NaN Error: temp_mc_watts')) + pause; + end + + azimuth_agg_dBm(azi_start:azi_end)=pow2db(sum(binary_sort_mc_watts,1,"omitnan")*1000); + end + + sub_array_agg_check_mc_dBm(loop_idx,:)=azimuth_agg_dBm; +end + +end diff --git a/validate_subchunk_agg_check_rev8_rev1.m b/validate_subchunk_agg_check_rev8_rev1.m new file mode 100644 index 0000000..919ac20 --- /dev/null +++ b/validate_subchunk_agg_check_rev8_rev1.m @@ -0,0 +1,50 @@ +function results = validate_subchunk_agg_check_rev8_rev1(app,cell_aas_dist_data,array_bs_azi_data,radar_beamwidth,min_azimuth,max_azimuth,base_protection_pts,point_idx,on_list_bs,cell_sim_chuck_idx,rand_seed1,agg_check_reliability,on_full_Pr_dBm,clutter_loss,custom_antenna_pattern,sub_point_idx) +%VALIDATE_SUBCHUNK_AGG_CHECK_REV8_REV1 Compare rev7 vs rev8 output and runtime. + +args = {app,cell_aas_dist_data,array_bs_azi_data,radar_beamwidth,min_azimuth,max_azimuth, ... + base_protection_pts,point_idx,on_list_bs,cell_sim_chuck_idx,rand_seed1, ... + agg_check_reliability,on_full_Pr_dBm,clutter_loss,custom_antenna_pattern,sub_point_idx}; + +t7=tic; +out7=subchunk_agg_check_rev7(args{:}); +time_rev7=toc(t7); + +t8=tic; +out8_a=subchunk_agg_check_rev8(args{:}); +time_rev8=toc(t8); + +out8_b=subchunk_agg_check_rev8(args{:}); + +results=struct(); +results.size_equal=isequal(size(out7),size(out8_a)); +results.nan_pattern_equal=isequal(isnan(out7),isnan(out8_a)); + +valid_mask=~isnan(out7) & ~isnan(out8_a); +if any(valid_mask,'all') + diff_abs=abs(out8_a(valid_mask)-out7(valid_mask)); + results.max_abs_diff=max(diff_abs,[],'all'); + results.mean_abs_diff=mean(diff_abs,'all'); +else + results.max_abs_diff=NaN; + results.mean_abs_diff=NaN; +end + +results.rev8_reproducible=isequaln(out8_a,out8_b); +results.rev7_runtime_s=time_rev7; +results.rev8_runtime_s=time_rev8; +results.percent_improvement=((time_rev7-time_rev8)/time_rev7)*100; + +tol=1e-9; +results.equivalent_within_tol=results.nan_pattern_equal && all(abs(out8_a(valid_mask)-out7(valid_mask))<=tol,'all'); + +fprintf('size_equal: %d\n',results.size_equal); +fprintf('nan_pattern_equal: %d\n',results.nan_pattern_equal); +fprintf('max_abs_diff: %.12g\n',results.max_abs_diff); +fprintf('mean_abs_diff: %.12g\n',results.mean_abs_diff); +fprintf('rev8_reproducible: %d\n',results.rev8_reproducible); +fprintf('equivalent_within_tol(%.1e): %d\n',tol,results.equivalent_within_tol); +fprintf('runtime_rev7_s: %.6f\n',results.rev7_runtime_s); +fprintf('runtime_rev8_s: %.6f\n',results.rev8_runtime_s); +fprintf('percent_improvement: %.3f\n',results.percent_improvement); + +end