Reputation: 51
This is my first question I have asked on here, so please bear with me. I am not new to Matlab but have never used the MVNRND function before and my statistics knowledge is not strong. The summary of what I am attempting to do is as follows: I am trying to create a function that generates 2 correlated phase screens (NxN matrices) which will be used in an Electromagnetic Gaussian Schell-Model beam propagation simulation. The beam requires separate random phase screens for the X and Y polarization states. The code I have so far is below.
function [phz_x,phz_y]=GSM_phase_screen_2(l_phi_x,l_phi_y,sigma_phi_x, ...
sigma_phi_y,gamma,N,delta)
%GSM_PHASE_SCREEN_2
% This code generates two correlated 2-D NxN Gaussian Schell-Model (GSM)
% phase screens (matrices) of unit variance circular complex Gaussian
% random numbers for the X and Y polarization states provided l_phi_x,
% l_phi_y, sigma_phi_x, sigma_phi_y, and gamma. It utilizes the MVNRND
% Matlab function.
%
% l_phi_x: [m] correlation length in X phase screen
% l_phi_y: [m] correlation length in Y phase screen
% sigma_phi_x: phase variance in X phase screen
% sigma_phi_y: phase variance in Y phase screen
% gamma: correlation coefficient
% N: number of samples per side of grid
% delta: [m] sample grid spacing
%
% phz_x: [rad] 2-D phase screen for X polarization state
% phz_y: [rad] 2-D phase screen for Y polarization state
% ORIGINAL AUTHOR: Santasri Basu
% MODIFIED BY: Matthew Gridley
% Added input arguments needed to generate 2 correlated phase
% screens, updated PSD equations, and replaced RANDN with MVNRND
%
% Setup the Power Spectral Density (PSD)
del_f = 1 / (N*delta); % frequency grid spacing [1/m]
fx = (-N/2 : N/2-1) * del_f;
% Frequency grid
[fx,fy] = meshgrid(fx);
% GSM phase PSD
PSD_phi_x = (sigma_phi_x^2) * pi * (l_phi_x^2) * gamma * ...
exp(-((pi * l_phi_x)^2) * (fx.^2 + fy.^2));
PSD_phi_y = (sigma_phi_y^2) * pi * (l_phi_y^2) * gamma * ...
exp(-((pi * l_phi_y)^2) * (fx.^2 + fy.^2));
% Random draws of Fourier series coefficients
% (zero mean Gaussian random numbers)
%
% the 2 lines of code below need changed to generate the correlated random
% draws using MVNRND and GAMMA
cn_x = (randn(N) + 1i*randn(N)) .* sqrt(PSD_phi_x) * del_f;
cn_y = (randn(N) + 1i*randn(N)) .* sqrt(PSD_phi_y) * del_f;
% Synthesize the phase screens
phz_x = real(ift2(cn_x,1));
phz_y = real(ift2(cn_y,1));
end
function [g, x] = ift2(G, df)
% [g, x] = ift2(G, df)
% 2-D inverse Fourier transform that keeps the origin at the center of
% the grid.
%
% G: Complex field in frequency space
% df: Spacing in frequency space [m^-1]
% g: Complex field in coordinate space
% Core function written by Jason Schmidt
% Modified: 17 Apr 2010
% By: Daniel J. Wheeler
%
% x output added functionality by Michael Steinbock 6/8/2014
%
g = ifftshift(ifft2(ifftshift(G))) * (length(G) * df)^2;
%% Calc x:
if nargout == 2
N = size(G, 1);
x = (0 : N-1) / (N*delta_f);
end
In the code above, the two lines of code below the comments which start with "% Random draws of Fourier series coefficients" are where I need assistance. I previously made two matrices with the code you see but realized they are not Gaussian correlated. From the recommendation of my academic advisor, I should be using MVNRND to generate these phase screens. After reviewing the help file for MVNRND, I am lost at how to use it for this purpose. I have searched on here trying to find similar questions and answers with no luck, and I have searched Google as well. Can anyone assist with changing these two lines of code to utilize MVNRND. Thank you!
Upvotes: 1
Views: 752
Reputation: 51
enter code hereAfter a lot of research, I figured out how to use MVNRND to suit my purposes. My intent was to create 4 random NxN matricies to replace the 4 uses of randn(N) in the below code snippet. The reason I needed to replace these with MVNRND generated random matricies is so that they are correlated. In MVNRND, you have to provide a covariance matrix. This is what was stumping me.
cn_x = (randn(N) + 1i*randn(N)) .* sqrt(PSD_phi_x) * del_f;
cn_y = (randn(N) + 1i*randn(N)) .* sqrt(PSD_phi_y) * del_f;
To create it, I have 4 different random values of which I must calculate the variance(covariance) of the combination pairs: rx_real, rx_imag, ry_real, and ry_imag. Once I figured that out, I was able to create the covariance matrix.
The next issue was figuring out to what the 'cases' value in MVNRND needed to be set. I needed 4 correlated NxN matrices so I determined cases needed to be a 4xN^2 matrix. Then I was able to use the 'reshape' command to convert the MVNRND output into the 4 NxN matricies needed.
Please see code below. Hope this helps others out!
% Multivariate normal parameters
mu = zeros([1,4]); % Zero mean Gaussian
% Covariance matrix for 4 circular complex Gaussian random numbers:
% rx_real, rx_imag, ry_real, ry_imag
%
% [<rx_real rx_real> <rx_real rx_imag> <rx_real ry_real> <rx_real ry_imag>;
% <rx_imag rx_real> <rx_imag rx_imag> <rx_imag ry_real> <rx_imag ry_imag>;
% <ry_real rx_real> <ry_real rx_imag> <ry_real ry_real> <ry_real ry_imag>;
% <ry_imag rx_real> <ry_imag rx_imag> <ry_imag ry_real> <ry_imag ry_imag>]
sigma = [1 0 gamma 0;
0 1 0 gamma;
gamma 0 1 0;
0 gamma 0 1];
cases = N^2; % matrix of random vectors
r = mvnrnd(mu, sigma, cases); % gives a 512^2x4 double matrix
rx_real = reshape(r(:,1),[N N]);
rx_imag = reshape(r(:,2),[N N]);
ry_real = reshape(r(:,3),[N N]);
ry_imag = reshape(r(:,4),[N N]);
% Correlated random draws of Fourier series coefficients
cn_x = (rx_real + 1i*rx_imag) .* sqrt(PSD_phi_x) * del_f;
cn_y = (ry_real + 1i*ry_imag) .* sqrt(PSD_phi_y) * del_f;
Upvotes: 4