Hello,
Currently I am trying model the field at a certain pixel plane in kWave and compare it with the field modelled by Greens function.
The problem is that neither amplitudes, neither unwrapped phase match each other.
Source in kWave was a single pixel. Field modelled with Greens function is corresponding to the planar source (Rayleigh integral of it), the exact formula is (in Latex):
\begin{equation}
p(r,\theta,\phi) = \frac{e^{j(\omega t - k r)}}{r}D(\theta,\phi)
\end{equation}
\begin{equation}
D(\theta,\phi) = \frac{j \omega \rho}{2 \pi} \int\int_S U(x',y') e^{j(kx'\sin{\theta}\cos{\phi} + ky'\sin{\theta}\sin{\phi})}
\end{equation}
(also can be found in the book of Jakobsen, 'Radiation of Sound', page 48).
I was comparing Rayleigh integral of Greens function and to the one of kWave. I have tried in kWave to increase number of pixels and decrease pixel size up to 0.1 mm, tried lower cfl = 0.2 (normally I work at cfl = 0.3) and lower time step, tried ppw = 5 (normally I have 3) and changing none of those parameters helped.
I attach my code, maybe one has idea what can be wrong :)
clear all;
saveFolder = './Phantom_water';
mkdir(saveFolder);
Nx = 1600; % number of grid points in the x (row) direction
Ny = 1600; % number of grid points in the y (column) direction
dx = 0.00019; % grid point spacing in the x direction [m]
dy = dx; % grid point spacing in the y direction [m]
kgrid = makeGrid(Nx, dx, Ny, dy);
cWater = 1509.2;
radius = 0.13; % radius of aperture
PMLSIZE = 200; % size of perfectly matched layer for absorbing the wave at the boundaries of the domain
numSenders = 128; % num senders on a ring
% define the properties of the propagation medium
medium.sound_speed = zeros([Nx,Ny])+cWater; % [m/s]
medium.density = zeros([Nx,Ny])+1000;
medium.alpha_coeff = zeros([Nx,Ny]); % [dB/(MHz^y cm)]
medium.alpha_power = 1.01;
x1 = zeros(1600);
% water
sosPhantom = cWater.*ones(size(x1,1));
attPhantom = zeros(size(x1,1));
densityPhantom = 997.*ones(size(x1,1));
% create the time array
[kgrid.t_array, dt] = makeTime(kgrid, medium.sound_speed);
% defining the source pulse
source_mag = 1000; %20 % [Pa]
r = 0.13/dx;
fs=1/dt; % sample freq.
fmin = 1e6; % Hz, start frequency of transducer
fup = 0.25e6;
fmax = 2.5e6; % MHz
fThresh = -15; % threshold in dB for selection of frequencies
tukeyf = 0.25; % in case of tukey shape width of cutoff
bw = fmax - fmin;
fcenter = (fmin + fmax)/2;
t0 = 1e-6;
nt = 1920;
rPot = radius;
rRoI = 0.08;
tw = min(max(2/bw,20/fcenter),2*(rPot-rRoI)/cWater-t0); % length of pulse emitted
pulse = zeros(1,nt,'double');
nw0 = fix(t0/dt)+1; % time at which chirp will be emitted
nw1 = fix(tw/dt); % length of chirp
f0 = fcenter-bw/2; % = 1 MHZ
k = bw/tw;
t = linspace(0,1,nw1+1)*tw;
pulse(nw0:nw0+nw1) = sin(2*pi*(f0+k/2*t).*t).*tukeywin(nw1+1,tukeyf)'; % tukeyf = 0.125
pulse(length(kgrid.t_array)) = 0;
source.p = pulse.*source_mag';
CE = source.p;
% filter the source to remove high frequencies not supported by the grid
source.p = filterTimeSeries(kgrid, medium, source.p,'PPW',5);
CEFiltered = source.p;
% SENDERS
angleStepsSensorsSenders = 360/numSenders;
anglesSenders = 0:angleStepsSensorsSenders:359.9999;
source.p_mask = zeros(Nx, Ny);
source.p_mask(800,1484) = 1;
%% Definition of pixel plane in Cartesian Coords
xmaxT = sqrt(rPot^2 - rRoI^2);
Nx = 2*round(xmaxT/dx);
rGrid = dx*Nx/2;
points(:,1) = linspace(-rGrid,rGrid,Nx+1);
points(:,2) = -rRoI;
sensor.mask = points.';
rPos = points;
mediumOrig = medium;
simData.resolution.x = dx;
simData.resolution.y = dy;
simData.time.timearray = kgrid.t_array;
simData.time.step = dt;
simData.time.sampleFreq = fs;
simData.PMLsize = PMLSIZE;
simData.CE = CE;
simData.CEFiltered = CEFiltered';
if(exist('source_freq','var'))
simData.source.freq = source_freq;
end
simData.source.mag = source_mag;
if(exist('bw','var'))
simData.source.bw = bw;
end
simData.dim.x = kgrid.Nx;
simData.dim.y = kgrid.Ny;
simData.pos.x = kgrid.x_vec;
simData.pos.y = kgrid.y_vec;
simData.size.x = kgrid.x_size;
simData.size.y = kgrid.y_size;
% ROI definition for receiver plane and pulse calculation
rRoi = 0.08;
ROI = sqrt((kgrid.x).^2 + (kgrid.y).^2)<rRoi;
for sIdx = 1:numSenders
% define the acoustic parameters to record
sensor.record = {'p', 'p_final'};
% rotate the object, i.e. medium
medium.sound_speed = imrotate(mediumOrig.sound_speed, anglesSenders(sIdx),'bilinear','crop');
%medium.sound_speed(~ROI) = mediumOrig.sound_speed(1,1);
medium.density = imrotate(mediumOrig.density, anglesSenders(sIdx),'bilinear','crop');
%medium.density(~ROI) = mediumOrig.density(1,1);
medium.alpha_coeff = imrotate(mediumOrig.alpha_coeff, anglesSenders(sIdx),'bilinear','crop');
%medium.alpha_coeff(~ROI) = mediumOrig.alpha_coeff(1,1);
% run the simulation
[sensor_data] = kspaceFirstOrder2D(kgrid, medium, source, sensor,'RecordMovie',true,'DataCast','single','PMLInside',false,'PMLSize',PMLSIZE);
% getting back the data
AScans = sensor_data.p;
sensorPos = sensor_data.sensorPos; % actual receiver position with PML added. And in the same order as the A-Scans
save(fullfile(saveFolder,sprintf('s%03i.mat',sIdx)), 'AScans', 'sPos','rPos','sensorPos', 'sIdx', 'anglesSenders');
end
Best wishes,
Olga