├── .gitignore ├── outdoor_5.3GHz ├── collect_all_data.m ├── Readme.txt ├── Proc_data_latest.m ├── C01_3GPP_36873_3D_UMa_NLOS.asv └── C01_3GPP_36873_3D_UMa_NLOS.m ├── slurm └── data_gen_outdoor_slow.sh └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.mat 2 | data/* 3 | *.out -------------------------------------------------------------------------------- /outdoor_5.3GHz/collect_all_data.m: -------------------------------------------------------------------------------- 1 | clear all 2 | H_ul = []; 3 | H_dl = []; 4 | for iii = 1:10 5 | name = ['all_data',num2str(iii),'.mat']; 6 | load(name); 7 | H_ul = cat(1, H_ul, X_AE_UL); 8 | H_dl = cat(1, H_dl, X_AE); 9 | end 10 | % save('H_QuaDRiGa','H_dl','H_ul') 11 | % % MM1(:,:) = H_ul(1050,:,:); 12 | % % MM2(:,:) = H_dl(1050,:,:); 13 | % % figure(1) 14 | % % subplot(211) 15 | % % imagesc(abs(MM1)) 16 | % % subplot(212) 17 | % % imagesc(abs(MM2)) -------------------------------------------------------------------------------- /slurm/data_gen_outdoor_slow.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -l 2 | 3 | #SBATCH --mail-type=ALL 4 | #SBATCH --mail-user=mdelrosa@ucdavis.edu 5 | #SBATCH -p med 6 | #SBATCH --time=4-0 # 4 days-0 hours 7 | #SBATCH -c 1 # 1 cpu cores per node 8 | #SBATCH --mem=16000 # use max node 9 | # set a=batch_glob, then submit with the following line to get properly named jobs: 10 | # sbatch --export=a=$a,gen_dir=$b --job-name=outslow_$a data_gen_outdoor_slow.sh 11 | 12 | module load matlab/2019a 13 | matlab -r "addpath('${quadriga_src}'); cd ${gen_dir}; batch_num=${batch_num}; C01_3GPP_36873_3D_UMa_NLOS();" -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # quadriga-brat 2 | 3 | BRAT Lab files for generating Channel State Information (CSI) datasets with QuaDRiGa channel model. Source files must be downloaded from [QuaDRiGa](https://quadriga-channel-model.de/#Download) to run. 4 | 5 | ## Background 6 | 7 | Most papers only use COST2100 channel model for deep learning-based CSI estimation. To validate our new network, [MarkovNet](https://arxiv.org/abs/2009.09468), on additional CSI datasets, I am writing this repo for the QuaDRiGa channel model. 8 | 9 | Scenarios: 10 | - [TODO] Outdoor LOS, 5.3GHz, 32Tx/1Rx, UE Mobility of 0.9m/s, 1024 subcarriers or 20kHZ bandwidth 11 | - [DOING] Outdoor LOS, 300MHz, 32Tx/1Rx, UE Mobility of 0.9m/s, 1024 subcarriers or 20kHZ bandwidth 12 | -------------------------------------------------------------------------------- /outdoor_5.3GHz/Readme.txt: -------------------------------------------------------------------------------- 1 | QuaDRiGa requires lots of memory to generate data. Thus, we need to generate data iteratively. 2 | On the other hand, the generated data is in cell format. So we should transform them into matrix format to load in Python. 3 | Conduct following procedures to generate desired channels. 4 | 1. Place all the scripts in the "tutorials" folder. 5 | 2. Adjust desired setting and parameters of QuaDRiGa in "C01_3GPP_36873_UMa_NLOS" 6 | 3. To transform data from cell format to matrix format using "Proc_data" 7 | 4. Collect all the data and save as a mat file using "collect_all_data" 8 | 9 | From Max's email (2021-01-05): 10 | 11 | The attached link is for the data generated by QuaDRiGa. 12 | A 32-antenna ULA is considered at gNB side and UE only has one antenna. 13 | All antennas are assumed to be omnidirectional. 14 | The uplink and downlink operating frequencies are at 5.1 and 5.3 GHz, respectively. 15 | Each of them uses a bandwidth of 20 MHz with 1024 subcarriers. 16 | The heights of UEs and BS are set at 1.5 and 20 meters. 17 | The channel model is 3GPP UMa outdoor-to-outdoor 3D channel model. 18 | The channel matrices with the size of 32 by 64 are obtained by doing 2D FFT, shifting the angle domain, and discarding the redundant region. 19 | The number of 64 is chosen because there are largely delayed paths in this outdoor channel model. 20 | -------------------------------------------------------------------------------- /outdoor_5.3GHz/Proc_data_latest.m: -------------------------------------------------------------------------------- 1 | %% 2 | clear all 3 | CCM_UL = []; 4 | CCM_DL = []; 5 | count = 0; 6 | for iii = 1:10 % recommend to process 10 files a time, otherwise, it will be out of memory. 7 | name = ['matnew',num2str(iii),'.mat']; 8 | load(name); 9 | for idx = 1:1000 10 | CCM_UL = [CCM_UL; CCM{1,idx}]; 11 | CCM_DL = [CCM_DL; CCM{2,idx}]; 12 | end 13 | iii 14 | end 15 | clear CCM 16 | CCM_DL_final = zeros(count, N*M, No_subcarrier, 1); 17 | CCM_UL_final = zeros(count, N*M, No_subcarrier, 1); 18 | for iii = 1:count 19 | CCM_DL_final(iii,:, :) = CCM_DL((iii-1)*N*M+1:iii*N*M, :); 20 | CCM_UL_final(iii,:, :) = CCM_UL((iii-1)*N*M+1:iii*N*M, :); 21 | end 22 | % angular fft 23 | MAP_2D_UL = (fft(CCM_DL_final, M, 2)); 24 | MAP_2D_DL = (fft(CCM_UL_final, M, 2)); 25 | 26 | % delay fft 27 | MAP_3D_UL = fftshift(fft(MAP_2D_UL, No_subcarrier, 3)); 28 | MAP_3D_DL = fftshift(fft(MAP_2D_DL, No_subcarrier, 3)); 29 | 30 | % discard reduntdunt information 31 | list_remove = [[1:No_subcarrier/2-32] [No_subcarrier/2+33:No_subcarrier]]; 32 | MAP_3D_UL(:,:,list_remove) = []; 33 | MAP_3D_DL(:,:,list_remove) = []; 34 | 35 | 36 | X_AE = MAP_3D_DL; 37 | X_AE_UL = MAP_3D_UL; 38 | 39 | % % % iiii = 1; 40 | % % % no_sc = 1024; 41 | % % % VVVV(:,:) = X_AE(iiii,:,:); 42 | % % % Map = abs(VVVV); 43 | % % % AA = angle(VVVV); 44 | % % % RR = real(VVVV); 45 | % % % II = imag(VVVV); 46 | % % % figure(112); 47 | % % % subplot(411) 48 | % % % imagesc(Map.'); 49 | % % % subplot(412) 50 | % % % imagesc(AA.'); 51 | % % % subplot(413) 52 | % % % imagesc(RR.'); 53 | % % % subplot(414) 54 | % % % imagesc(II.'); 55 | % X_UL_norm = permute(X_UL_norm,[2 1 3]); 56 | % X_AE = permute(X_AE,[2 1 3]); 57 | % Y_AE = permute(Y_AE,[2 1 3]); 58 | 59 | % iii =600; 60 | % XX(:,:) = X_AE(iii,:,:); YY(:,:) = X_UL_norm(iii,:,:); 61 | % figure(1);subplot(211);imagesc(abs(XX));subplot(212);imagesc(abs(YY)) 62 | 63 | save('all_data10.mat','X_AE','X_AE_UL') -------------------------------------------------------------------------------- /outdoor_5.3GHz/C01_3GPP_36873_3D_UMa_NLOS.asv: -------------------------------------------------------------------------------- 1 | %% Multi-frequency simulations 2 | 3 | % This tutorial demonstrates how to perform simultaneous multi-frequency simulations at two carrier 4 | % frequencies: 2.6 GHz and 28 GHz in an Urban-Macrocell deployment. The BS is equipped with two 5 | % different array antennas. A conventional high-gain antenna operates at 2.6 GHz. The higher 6 | % frequency band uses a massive-MIMO array antenna with in an 8x8 dual-polarized setup. The model is 7 | % consistent in both, the spatial domain and the frequency domain. Simulation assumptions are in 8 | % accordance with 3GPP 38.901 v14.1.0 (see Section 7.6.5 Correlation modeling for multi-frequency 9 | % simulations). 10 | % 11 | % Identical parameters for each frequency: 12 | % 13 | % * LOS / NLOS state must be the same 14 | % * BS and MT positions are the same (antenna element positions are different!) 15 | % * Cluster delays and angles for each multi-path component are the same 16 | % * Spatial consistency of the LSPs is identical 17 | % 18 | % Differences: 19 | % 20 | % * Antenna patterns are different for each frequency 21 | % * Path-loss is different for each frequency 22 | % * Path-powers are different for each frequency 23 | % * Delay- and angular spreads are different 24 | % * K-Factor is different 25 | % * XPR of the NLOS components is different 26 | 27 | 28 | %% Basic setup 29 | % Multiple frequencies are set in the simulation parameters by providing a vector of frequency 30 | % sample points. A new layout is created with one 25 m high BS positions and 100 MT positions. The 31 | % MTs are placed in accordance with the 3GPP assumptions, where 80% of them are situated indoors at 32 | % different floor levels. 33 | 34 | % for mobile MTs, we define the following: 35 | sample_density = 1.2; % [samples / half wavelength] 36 | % track_distance = 0.25; % [meters] - for 5.2GHz 37 | track_distance = 4; % [meters] - for 300MHz 38 | area_len = 400; % area of MT initial positions [meters] 39 | area_half = area_len/2; 40 | timeslots = 10; 41 | N_samples = 10; 42 | best_shift = 32; 43 | 44 | batch_num = 1; % TODO: change batch_num based on input arg/env var 45 | H_ang_down = zeros(N_samples,timeslots,M,no_sc); 46 | H_ang_up = zeros(N_samples,timeslots,M,no_sc); 47 | 48 | % k -- shifting sweep 49 | k_lim = 128; 50 | k_list = (-k_lim:k_lim); 51 | pow_ratio = zeros(1,length(k_list)); 52 | batch_times = zeros(1,N_samples); 53 | 54 | for i_sample = 1:N_samples 55 | 56 | strout=sprintf("Sample %03d -> ", i_sample); 57 | fprintf(strout); 58 | tic 59 | 60 | set(0,'defaultTextFontSize', 18) % Default Font Size 61 | set(0,'defaultAxesFontSize', 18) % Default Font Size 62 | set(0,'defaultAxesFontName','Times') % Default Font Type 63 | set(0,'defaultTextFontName','Times') % Default Font Type 64 | set(0,'defaultFigurePaperPositionMode','auto') % Default Plot position 65 | set(0,'DefaultFigurePaperType','') % Default Paper Type 66 | set(0,'DefaultFigurePaperSize',[14.5 7.7]) % Default Paper Size 67 | 68 | s = qd_simulation_parameters; 69 | % s.center_frequency = [5.1e9 5.1e9 5.3e9]; % Assign two frequencies, the first one is redundent frequency 70 | s.center_frequency = [2.6e8 2.6e8 3.0e8]; % Assign two frequencies, the first one is redundent frequency 71 | freq_str = '300MHz'; 72 | s.sample_density = sample_density; % from t_09_speed_profile_interpolation.m - samples per half-wavelength 73 | s.show_progress_bars = 0; % Disable progress bars 74 | no_user = 1; 75 | 76 | % from t09_speed_profile_interpolation.m - define a linear track for MT 77 | % to travel along based on random init position/direction 78 | 79 | % randomize init point for MT in square area defined by area_len 80 | x_i = area_len*rand(1) - area_half; 81 | y_i = area_len*rand(1) - area_half; 82 | theta = pi*(2*rand(1) - 1); 83 | t = qd_track('linear', track_distance, theta); % 20 m track, direction SE 84 | t.initial_position = [x_i; y_i; 1.5]; % Start position 85 | t.interpolate_positions( s.samples_per_meter ); % Apply sample density 86 | % t.interpolate_positions( 128/20 ); % Interpolate 87 | t.segment_index = [1]; % Assign segments 88 | % t.scenario = {'BERLIN_UMa_LOS','BERLIN_UMa_NLOS','BERLIN_UMa_LOS'}; 89 | t.scenario = {'3GPP_3D_UMa_LOS'}; 90 | t.name = 'Rx1'; 91 | 92 | % from t09_speed_profile_interpolation.m - apply linear track to link 93 | % layout handle 94 | l = qd_layout( s ); % New QuaDRiGa layout 95 | % l.tx_array = qd_arrayant('dipole'); % Set Dipole antenna 96 | % l.rx_array = qd_arrayant('dipole'); % Set Dipole antenna 97 | % l.tx_position(3) = 25; % BE height 98 | l.rx_track = t; % Assign track 99 | 100 | % l = qd_layout( s ); % New QuaDRiGa layout 101 | l.tx_position = [0 0 20]'; % 20 m BS height 102 | % l.no_rx = no_user; % 200 MTs 103 | 104 | % l.randomize_rx_positions( 100, 1.5, 1.5, 0 ); % Assign random user positions 105 | % l.rx_position(1,:) = l.rx_position(1,:) + 110; % 106 | 107 | % floor = randi(5,1,l.no_rx) + 3; % Set random floor levels 108 | % for n = 1:l.no_rx 109 | % floor( n ) = randi( floor( n ) ); 110 | % end 111 | % l.rx_position(3,:) = 3*(floor-1) + 1.5; 112 | 113 | % indoor_rx = l.set_scenario('3GPP_3D_UMa',[],[],0); % Set the scenario 114 | % l.rx_position(3,~indoor_rx) = 1.5; % Set outdoor-users to 1.5 m height 115 | % l.visualize 116 | 117 | N = 1; 118 | M = 32; 119 | %% Antenna set-up 120 | % Two different antenna configurations are used at the BS. The 2.6 GHz antenna is constructed from 8 121 | % vertically stacked patch elements with +/- 45 degree polarization. The electric downtilt is set to 122 | % 8 degree. The mm-wave antenna uses 64 dual-polarized elements in a 8x8 massive-MIMO array 123 | % configuration. The antennas are assigned to the BS by an array of "qd_arrayant" objects. Rows 124 | % correspond to the frequency, columns to the BS. There is only 1 BS in the layout. The mobile 125 | % terminal uses a vertically polarized omni-directional antenna for both frequencies. 126 | 127 | % a_35000_Mhz = qd_arrayant( '3gpp-3d', 16, 8, s.center_frequency(1), 6, 8 ); 128 | % a_35000_Mhz = qd_arrayant.generate( '3gpp-mmw', 16, 8, s.center_frequency(1), 6, 8 ); 129 | a_redundent = qd_arrayant.generate( '3gpp-3d', N, M, s.center_frequency(1), 1 ); % originally, last arg was 3 130 | a_uplink = qd_arrayant.generate( '3gpp-3d', N, M, s.center_frequency(2), 1 ); % yielded +/-45deg polarized 131 | a_downlink = qd_arrayant.generate( '3gpp-3d', N, M, s.center_frequency(3), 1 ); % elements, yielding 2x elementantennas per element 132 | 133 | 134 | l.tx_array(1,1) = a_redundent; % Set 2.6 GHz antenna 135 | l.tx_array(2,1) = a_51000_Mhz; 136 | l.tx_array(3,1) = a_downlink; 137 | 138 | l.rx_array = qd_arrayant('omni'); % Set omni-rx antenna 139 | 140 | 141 | %% Generate channel coefficients 142 | % Channel coefficients are generated by calling "l.get_channels". The output is an array of QuaDRiGa 143 | % channel objects. The first dimension corresponds to the MTs (100). The second dimension 144 | % corresponds to the number of BSs (1) and the third dimension corresponds to the number of 145 | % frequencies. 146 | 147 | c = l.get_channels; 148 | 149 | % get sample time 150 | t=toc; 151 | batch_times(i_sample) = t; 152 | avg_time = mean(batch_times(1:i_sample)); 153 | proj_time = (N_samples - i_sample)*avg_time / 60; 154 | strout=sprintf("Sample Time: %03.1f sec - Sample Avg. Time: %03.1f sec - Projected Batch Time: %03.1f min \n", t, avg_time, proj_time); 155 | fprintf(strout); 156 | 157 | CCM = cell(4,no_user); 158 | % delay = cell(4,no_user); 159 | % EoD = cell(4,no_user); 160 | % AoD = cell(4,no_user); 161 | % PW = cell(4,no_user); 162 | % CGain = cell(4,no_user); 163 | no_sc = 1024; 164 | sc_bw = 2e4; 165 | freq_response = zeros(2,timeslots,M,no_sc); % init freq response 166 | H_freq_down = zeros(timeslots,M,no_sc); 167 | H_freq_up = zeros(timeslots,M,no_sc); 168 | H_ang_down_sample = zeros(timeslots,M,no_sc); 169 | H_ang_up_sample = zeros(timeslots,M,no_sc); 170 | for idx_UD = 1:2 171 | for i = 1:no_user 172 | c(i,1,idx_UD+1).individual_delays = 0; 173 | end 174 | for t_i = 1:timeslots 175 | % TODO: magic number; why use 15000 in this line? 176 | % my guess: this is subcarrier bandwidth 177 | H_freq_down(t_i,:,:) = c(1,2).fr(no_sc*sc_bw,no_sc,t_i); %clear CFR; CFR(:) = abs(freq_response(1,:,3)); CFR = CFR(1:2:end); 178 | H_freq_up(t_i,:,:) = c(1,3).fr(no_sc*sc_bw,no_sc,t_i); 179 | % H_freq_down(t_i,:,:) = c(1,2).coeff; %clear CFR; CFR(:) = abs(freq_response(1,:,3)); CFR = CFR(1:2:end); 180 | % H_freq_up(t_i,:,:) = c(1,3).coeff; 181 | % CCM{idx_UD,iii}(:,:) = freq_response(idx_UD+1,iii,1:2:end,:); % Channel Coefficient Matrix (or CFR) 182 | % delay{idx_UD,iii}(:) = c(iii,1,idx_UD+1).delay; 183 | % EoD{idx_UD,iii}(:) = c(iii,1,idx_UD+1).par.EoD_cb; 184 | % AoD{idx_UD,iii}(:) = c(iii,idx_UD+1).par.AoD_cb; 185 | % PW{idx_UD,iii}(:) = c(iii,idx_UD+1).par.pow_cb; 186 | % CGain{idx_UD,iii}(:) = c(iii,idx_UD+1).coeff(1,1,:); 187 | H_ang_down_sample(t_i,:,:) = fft(squeeze(H_freq_down(t_i,:,:)), [], 2); 188 | % H_ang_down_sample(t_i,:,:) = ifft(H_ang_down_sample(t_i,:,:), [], 1); 189 | H_ang_up_sample(t_i,:,:) = fft(squeeze(H_freq_up(t_i,:,:)), [], 2); 190 | % H_ang_up_sample(t_i,:,:) = ifft(H_ang_up_sample(t_i,:,:), [], 1); 191 | end 192 | end 193 | % f1 = ['matnew' num2str(number) '.mat']; 194 | % save(f1,'CCM') 195 | % clear all 196 | 197 | if best_shift ~= 0 198 | H_ang_down(i_sample,:,:,:) = circshift(H_ang_down_sample, best_shift, 3); 199 | H_ang_up(i_sample,:,:,:) = circshift(H_ang_up_sample, best_shift, 3); 200 | elseif isnan(best_shift) 201 | for k = k_list 202 | a_shift = squeeze(circshift(H_ang_t1,k,2)); % for T = 1 203 | % a_shift = squeeze(circshift(a_at(timeslot,:,:),k,2)); % for T > 1 204 | temp = sum(a_shift(:,1:32).*conj(a_shift(:,1:32)), 'all'); 205 | pow_ratio(k+k_lim+1) = pow_ratio(k+k_lim+1) + (temp / sum(a_shift.*conj(a_shift), 'all')) / N_samples; 206 | end 207 | end 208 | 209 | end 210 | 211 | f_down = sprintf('H_ang_down_quadriga_b%d.mat', batch_num); 212 | f_up = sprintf('H_ang_up_quadriga_b%d.mat', batch_num); 213 | save(f_down,'H_ang_down'); 214 | save(f_up,'H_ang_up'); 215 | % clear all; 216 | 217 | %% plot circ 218 | 219 | [m, idx] = max(pow_ratio); 220 | 221 | figure(1); clf; hold on; 222 | plot(k_list,pow_ratio); 223 | % title_str = sprintf('Circular Shift on Indoor 5.3GHz (max=%d)', idx - (k_lim+1)); 224 | ylabel('P_{truncate} / P_{total}'); 225 | xlabel('k'); 226 | title(sprintf('Quadriga Circular Shift on %s (max=%d, N=%d samples)', freq_str, idx-(k_lim+1), N_samples)); 227 | 228 | 229 | %% sanity checking - angular delay domain 230 | figure(2); clf; hold on; 231 | H_ang_down_samp = squeeze(H_ang_down(1,1,:,:)); 232 | for t_i = 1:timeslots 233 | row = round(t_i / timeslots) + 1; 234 | col = round(t_i / timeslots) + 1; 235 | subplot(2,5,t_i); 236 | % H_ang_down = ifft(squeeze(H_freq_down(t_i,:,:)), [], 1); 237 | % H_ang_down = fft(H_ang_down, [], 2); 238 | % surf(10*log10(abs(H_ang_down)), 'EdgeColor', 'none'); 239 | % H_ang_up= ifft(squeeze(H_freq_down(t_i,:,:)), [], 1); 240 | % H_ang_up = fft(H_ang_up, [], 2); 241 | % H_ang_up = fft(squeeze(H_ang_down_samp(t_i,:,:)), [], 2); 242 | % H_ang_up = ifft(H_ang_up, [], 1); 243 | surf(10*log10(abs(H_ang_down_samp)), 'EdgeColor', 'none'); 244 | view(0,90); 245 | xlabel('delay'); 246 | ylabel('angle'); 247 | title(sprintf("t_{%d}", t_i)); 248 | end 249 | % sgtitle("QuaDRiGa -- Outdoor 5.3GHz - 0.9m/s mobility - 40ms feedback interval"); 250 | sgtitle(sprintf("QuaDRiGa -- Outdoor 300MHz - 0.9m/s mobility - 40ms feedback interval - k_{shift}=%d", best_shift)); 251 | 252 | %% inspect power ratio for different truncation windows 253 | % truncate_lim = 128; 254 | % truncate_stride = 4; 255 | % l_list = (0:truncate_stride:truncate_lim); 256 | % pow_list = zeros(1,length(l_list)); 257 | % 258 | % for l = l_list 259 | % a_drop = H_ang_down(l+1:end,:); 260 | % % del, ang = size(a_drop); 261 | % pow_idx = round(l/truncate_stride)+1; 262 | % pow_list(pow_idx) = pow_list(pow_idx) + (sqrt(sum(a_drop .* conj(a_drop), 'all')) / N_samples); 263 | % end 264 | % 265 | % figure(3); clf; hold on; 266 | % plot(l_list, pow_list); -------------------------------------------------------------------------------- /outdoor_5.3GHz/C01_3GPP_36873_3D_UMa_NLOS.m: -------------------------------------------------------------------------------- 1 | %% Multi-frequency simulations 2 | 3 | % This tutorial demonstrates how to perform simultaneous multi-frequency simulations at two carrier 4 | % frequencies: 2.6 GHz and 28 GHz in an Urban-Macrocell deployment. The BS is equipped with two 5 | % different array antennas. A conventional high-gain antenna operates at 2.6 GHz. The higher 6 | % frequency band uses a massive-MIMO array antenna with in an 8x8 dual-polarized setup. The model is 7 | % consistent in both, the spatial domain and the frequency domain. Simulation assumptions are in 8 | % accordance with 3GPP 38.901 v14.1.0 (see Section 7.6.5 Correlation modeling for multi-frequency 9 | % simulations). 10 | % 11 | % Identical parameters for each frequency: 12 | % 13 | % * LOS / NLOS state must be the same 14 | % * BS and MT positions are the same (antenna element positions are different!) 15 | % * Cluster delays and angles for each multi-path component are the same 16 | % * Spatial consistency of the LSPs is identical 17 | % 18 | % Differences: 19 | % 20 | % * Antenna patterns are different for each frequency 21 | % * Path-loss is different for each frequency 22 | % * Path-powers are different for each frequency 23 | % * Delay- and angular spreads are different 24 | % * K-Factor is different 25 | % * XPR of the NLOS components is different 26 | 27 | 28 | %% Basic setup 29 | % Multiple frequencies are set in the simulation parameters by providing a vector of frequency 30 | % sample points. A new layout is created with one 25 m high BS positions and 100 MT positions. The 31 | % MTs are placed in accordance with the 3GPP assumptions, where 80% of them are situated indoors at 32 | % different floor levels. 33 | 34 | % define batch_num/N_samples 35 | debug_flag = 0; 36 | if debug_flag==0 37 | N_samples = 2500; 38 | else 39 | N_samples = 10; 40 | end 41 | 42 | try 43 | if ~batch_num 44 | batch_num = 1; 45 | end 46 | catch 47 | fprintf('Batch number undefined. Setting batch_num=1\n'); 48 | batch_num = 1; 49 | end 50 | 51 | % seed random number generator; prevent identical datasets between different batches 52 | rng(batch_num*10); 53 | 54 | % for mobile MTs, we define the following: 55 | sample_density = 1.2; % [samples / half wavelength] 56 | % track_distance = 0.25; % [meters] - for 5.2GHz 57 | track_distance = 4; % [meters] - for 300MHz 58 | track_speed = 0.9; % [meters/second] - for 300MHz 59 | feedback_interval = 0.04; % [seconds] 60 | 61 | area_len = 400; % area of MT initial positions [meters] 62 | area_half = area_len/2; 63 | timeslots = 10; 64 | feedback_times = (0:timeslots-1)*feedback_interval; 65 | feedback_locs = feedback_times*track_speed; 66 | feedback_profile = [feedback_times; feedback_locs]; 67 | best_shift = 84; 68 | 69 | N = 1; 70 | M = 32; 71 | no_sc = 1024; 72 | sc_bw = 2e4; 73 | n_truncate = 96; 74 | 75 | Hur_down = zeros(N_samples,timeslots,M,n_truncate); 76 | Hur_up = zeros(N_samples,timeslots,M,n_truncate); 77 | P_excess_down = zeros(N_samples,timeslots); 78 | P_excess_up = zeros(N_samples,timeslots); 79 | 80 | % k -- shifting sweep 81 | k_lim = 256; 82 | k_list = (-k_lim:k_lim); 83 | pow_ratio = zeros(1,length(k_list)); 84 | batch_times = zeros(1,N_samples); 85 | 86 | fprintf(sprintf('Batch #%d -- %d samples. \n',batch_num,N_samples)); 87 | 88 | for i_sample = 1:N_samples 89 | 90 | strout=sprintf("Sample %03d / %03d -> ", i_sample, N_samples); 91 | fprintf(strout); 92 | tic 93 | 94 | set(0,'defaultTextFontSize', 18) % Default Font Size 95 | set(0,'defaultAxesFontSize', 18) % Default Font Size 96 | set(0,'defaultAxesFontName','Times') % Default Font Type 97 | set(0,'defaultTextFontName','Times') % Default Font Type 98 | set(0,'defaultFigurePaperPositionMode','auto') % Default Plot position 99 | set(0,'DefaultFigurePaperType','') % Default Paper Type 100 | set(0,'DefaultFigurePaperSize',[14.5 7.7]) % Default Paper Size 101 | 102 | s = qd_simulation_parameters; 103 | % s.center_frequency = [5.1e9 5.1e9 5.3e9]; % Assign two frequencies, the first one is redundent frequency 104 | s.center_frequency = [2.6e8 2.6e8 3.0e8]; % Assign two frequencies, the first one is redundent frequency 105 | freq_str = '300MHz'; 106 | s.sample_density = sample_density; % from t_09_speed_profile_interpolation.m - samples per half-wavelength 107 | s.show_progress_bars = 0; % Disable progress bars 108 | no_user = 1; 109 | 110 | % from t09_speed_profile_interpolation.m - define a linear track for MT 111 | % to travel along based on random init position/direction 112 | 113 | % randomize init point for MT in square area defined by area_len 114 | x_i = area_len*rand(1) - area_half; 115 | y_i = area_len*rand(1) - area_half; 116 | theta = pi*(2*rand(1) - 1); 117 | t = qd_track('linear', track_distance, theta); % 20 m track, direction SE 118 | t.initial_position = [x_i; y_i; 1.5]; % Start position 119 | % t.interpolate_positions( s.samples_per_meter ); % Apply sample density 120 | t.set_speed( track_speed ); % Apply sample density 121 | t.interpolate( 'time', feedback_interval, feedback_profile ); 122 | % t.interpolate_positions( 128/20 ); % Interpolate 123 | t.segment_index = [1]; % Assign segments 124 | % t.scenario = {'BERLIN_UMa_LOS','BERLIN_UMa_NLOS','BERLIN_UMa_LOS'}; 125 | t.scenario = {'3GPP_3D_UMa_LOS'}; 126 | t.name = 'Rx1'; 127 | 128 | % from t09_speed_profile_interpolation.m - apply linear track to link 129 | % layout handle 130 | l = qd_layout( s ); % New QuaDRiGa layout 131 | % l.tx_array = qd_arrayant('dipole'); % Set Dipole antenna 132 | % l.rx_array = qd_arrayant('dipole'); % Set Dipole antenna 133 | % l.tx_position(3) = 25; % BE height 134 | l.rx_track = t; % Assign track 135 | 136 | % l = qd_layout( s ); % New QuaDRiGa layout 137 | l.tx_position = [0 0 20]'; % 20 m BS height 138 | % l.no_rx = no_user; % 200 MTs 139 | 140 | % l.randomize_rx_positions( 100, 1.5, 1.5, 0 ); % Assign random user positions 141 | % l.rx_position(1,:) = l.rx_position(1,:) + 110; % 142 | 143 | % floor = randi(5,1,l.no_rx) + 3; % Set random floor levels 144 | % for n = 1:l.no_rx 145 | % floor( n ) = randi( floor( n ) ); 146 | % end 147 | % l.rx_position(3,:) = 3*(floor-1) + 1.5; 148 | 149 | % indoor_rx = l.set_scenario('3GPP_3D_UMa',[],[],0); % Set the scenario 150 | % l.rx_position(3,~indoor_rx) = 1.5; % Set outdoor-users to 1.5 m height 151 | % l.visualize 152 | 153 | %% Antenna set-up 154 | % Two different antenna configurations are used at the BS. The 2.6 GHz antenna is constructed from 8 155 | % vertically stacked patch elements with +/- 45 degree polarization. The electric downtilt is set to 156 | % 8 degree. The mm-wave antenna uses 64 dual-polarized elements in a 8x8 massive-MIMO array 157 | % configuration. The antennas are assigned to the BS by an array of "qd_arrayant" objects. Rows 158 | % correspond to the frequency, columns to the BS. There is only 1 BS in the layout. The mobile 159 | % terminal uses a vertically polarized omni-directional antenna for both frequencies. 160 | 161 | % a_35000_Mhz = qd_arrayant( '3gpp-3d', 16, 8, s.center_frequency(1), 6, 8 ); 162 | % a_35000_Mhz = qd_arrayant.generate( '3gpp-mmw', 16, 8, s.center_frequency(1), 6, 8 ); 163 | a_redundent = qd_arrayant.generate( '3gpp-3d', N, M, s.center_frequency(1), 1 ); % originally, last arg was 3 164 | a_uplink = qd_arrayant.generate( '3gpp-3d', N, M, s.center_frequency(2), 1 ); % yielded +/-45deg polarized 165 | a_downlink = qd_arrayant.generate( '3gpp-3d', N, M, s.center_frequency(3), 1 ); % elements, yielding 2x elements/antenna 166 | 167 | l.tx_array(1,1) = a_redundent; 168 | l.tx_array(2,1) = a_uplink; 169 | l.tx_array(3,1) = a_downlink; 170 | 171 | l.rx_array = qd_arrayant('omni'); % Set omni-rx antenna 172 | 173 | 174 | %% Generate channel coefficients 175 | % Channel coefficients are generated by calling "l.get_channels". The output is an array of QuaDRiGa 176 | % channel objects. The first dimension corresponds to the MTs (100). The second dimension 177 | % corresponds to the number of BSs (1) and the third dimension corresponds to the number of 178 | % frequencies. 179 | 180 | c = l.get_channels; 181 | 182 | % get sample time 183 | t=toc; 184 | batch_times(i_sample) = t; 185 | avg_time = mean(batch_times(1:i_sample)); 186 | proj_time = (N_samples - i_sample)*avg_time / 60; 187 | strout=sprintf("Sample Time: %03.1f sec - Sample Avg. Time: %03.1f sec - Projected Batch Time: %03.1f min \n", t, avg_time, proj_time); 188 | fprintf(strout); 189 | 190 | freq_response = zeros(2,timeslots,M,no_sc); % init freq response 191 | H_freq_down = zeros(timeslots,M,no_sc); 192 | H_freq_up = zeros(timeslots,M,no_sc); 193 | H_ang_down_sample = zeros(timeslots,M,no_sc); 194 | H_ang_up_sample = zeros(timeslots,M,no_sc); 195 | for t_i = 1:timeslots 196 | H_freq_down(t_i,:,:) = c(1,2).fr(no_sc*sc_bw,no_sc,t_i); %clear CFR; CFR(:) = abs(freq_response(1,:,3)); CFR = CFR(1:2:end); 197 | H_freq_up(t_i,:,:) = c(1,3).fr(no_sc*sc_bw,no_sc,t_i); 198 | H_ang_down_sample(t_i,:,:) = fft(squeeze(H_freq_down(t_i,:,:)), [], 2); 199 | H_ang_down_sample(t_i,:,:) = ifft(H_ang_down_sample(t_i,:,:), [], 1); 200 | H_ang_up_sample(t_i,:,:) = fft(squeeze(H_freq_up(t_i,:,:)), [], 2); 201 | H_ang_up_sample(t_i,:,:) = ifft(H_ang_up_sample(t_i,:,:), [], 1); 202 | end 203 | try 204 | H_ang_down_sample = circshift(H_ang_down_sample, best_shift, 3); 205 | H_ang_up_sample = circshift(H_ang_up_sample, best_shift, 3); 206 | catch 207 | for k = k_list 208 | a_shift = circshift(squeeze(H_ang_down_sample(1,:,:)),k,2); % for T = 1 209 | % a_shift = squeeze(circshift(a_at(timeslot,:,:),k,2)); % for T > 1 210 | temp = sum(a_shift(:,1:n_truncate).*conj(a_shift(:,1:n_truncate)), 'all'); 211 | pow_ratio(k+k_lim+1) = pow_ratio(k+k_lim+1) + (temp / sum(a_shift.*conj(a_shift), 'all')) / N_samples; 212 | end 213 | end 214 | 215 | Hur_down(i_sample,:,:,:) = H_ang_down_sample(:,:,1:n_truncate); 216 | Hur_up(i_sample,:,:,:) = H_ang_up_sample(:,:,1:n_truncate); 217 | P_excess_down(i_sample,:) = sum(sum(conj(H_ang_down_sample(:,:,n_truncate+1:end)).*H_ang_down_sample(:,:,n_truncate+1:end), 2), 3); 218 | P_excess_up(i_sample,:) = sum(sum(conj(H_ang_up_sample(:,:,n_truncate+1:end)).*H_ang_up_sample(:,:,n_truncate+1:end), 2), 3); 219 | end 220 | 221 | f_down = sprintf('H_ang_quadriga_%d_down.mat', batch_num); 222 | f_up = sprintf('H_ang_quadriga_%d_up.mat', batch_num); 223 | P_down = sprintf('P_excess_quadriga_%d_down.mat', batch_num); 224 | P_up = sprintf('P_excess_quadriga_%d_up.mat', batch_num); 225 | save(f_down,'Hur_down'); 226 | save(f_up,'Hur_up'); 227 | save(P_down,'P_excess_down'); 228 | save(P_up,'P_excess_up'); 229 | % clear all; 230 | 231 | %% plot circ 232 | 233 | if debug_flag 234 | try 235 | [m, idx] = max(pow_ratio); 236 | 237 | figure(1); clf; hold on; 238 | plot(k_list,pow_ratio); 239 | % title_str = sprintf('Circular Shift on Indoor 5.3GHz (max=%d)', idx - (k_lim+1)); 240 | ylabel('P_{truncate} / P_{total}'); 241 | title(sprintf('Quadriga Circular Shift on %s (max=%d, N=%d samples)', freq_str, idx-(k_lim+1), N_samples)); 242 | catch 243 | fprintf("--- best_shift defined. Skipping pow_ratio plot. ---"); 244 | end 245 | 246 | 247 | %% sanity checking - angular delay domain 248 | figure(2); clf; hold on; 249 | H_samp = squeeze(H_ang_down_sample); 250 | for t_i = 1:timeslots 251 | row = round(t_i / timeslots) + 1; 252 | col = round(t_i / timeslots) + 1; 253 | subplot(2,5,t_i); 254 | surf(10*log10(abs(squeeze(H_samp(t_i,:,1:n_truncate)))), 'EdgeColor', 'none'); 255 | view(0,90); 256 | xlabel('delay'); 257 | ylabel('angle'); 258 | title(sprintf("t_{%d}", t_i)); 259 | end 260 | % sgtitle("QuaDRiGa -- Outdoor 5.3GHz - 0.9m/s mobility - 40ms feedback interval"); 261 | sgtitle("QuaDRiGa -- Outdoor 300MHz - 0.9m/s mobility - 40ms feedback interval"); 262 | 263 | %% inspect power ratio for different truncation windows 264 | % truncate_lim = 128; 265 | % truncate_stride = 4; 266 | % l_list = (0:truncate_stride:truncate_lim); 267 | % pow_list = zeros(1,length(l_list)); 268 | % 269 | % for l = l_list 270 | % a_drop = H_ang_down(l+1:end,:); 271 | % del, ang = size(a_drop); 272 | % pow_idx = round(l/truncate_stride)+1; 273 | % pow_list(pow_idx) = pow_list(pow_idx) + (sqrt(sum(a_drop .* conj(a_drop), 'all')) / N_samples); 274 | % end 275 | % 276 | % figure(3); clf; hold on; 277 | % plot(l_list, pow_list); 278 | end --------------------------------------------------------------------------------