% DESCRIPTION:
%       subscript to save input data to disk
%
% ABOUT:
%       author      - Bradley Treeby and Jiri Jaros
%       date        - 24th August 2011
%       last update - 16th December 2011
%       
% This function is part of the k-Wave Toolbox (http://www.k-wave.org)
% Copyright (C) 2009, 2010, 2011 Bradley Treeby and Ben Cox

% This file is part of k-Wave. k-Wave is free software: you can
% redistribute it and/or modify it under the terms of the GNU Lesser
% General Public License as published by the Free Software Foundation,
% either version 3 of the License, or (at your option) any later version.
% 
% k-Wave is distributed in the hope that it will be useful, but WITHOUT ANY
% WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
% FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
% more details. 
% 
% You should have received a copy of the GNU Lesser General Public License
% along with k-Wave. If not, see <http://www.gnu.org/licenses/>.

% =========================================================================
% VARIABLE LIST
% =========================================================================

% list of all the static variables used within the time loop
variable_list = {'p0', 'dt', ...
    'pml_x_sgx', 'pml_y_sgy', 'pml_z_sgz', 'pml_x', 'pml_y', 'pml_z', ...
    'rho0', 'rho0_sgx', 'rho0_sgy', 'rho0_sgz', 'c', ...    
    'kappa_r', ...
    'ddx_k_shift_pos_r', 'ddx_k_shift_neg_r', ...
    'ddy_k_shift_pos', 'ddy_k_shift_neg', ... 
    'ddz_k_shift_pos', 'ddz_k_shift_neg', ...        
    'absorb_tau', 'absorb_eta', ...
    'absorb_nabla1_r', 'absorb_nabla2_r', ...    
    'BonA', ...
    'transducer_input_signal'};

% list of all the integer variables used within the time loop
integer_variable_list = {'sensor_mask_ind', 'us_index', 'delay_mask', 'transducer_source',...
    'us_index_size', 'sensor_mask_index_size', 'transducer_input_signal_size',...
    'Nx', 'Ny', 'Nz', 'Nx_r', 'Nt'};

% =========================================================================
% PREPARE AND CREATE REQUIRED C/C++ VARIABLES
% =========================================================================

% assign pseudo-names for the variables stored in structures
Nx = kgrid.Nx;
Ny = kgrid.Ny;
Nz = kgrid.Nz;
Nt = length(t_array);
BonA = medium.BonA;
if isfield(source, 'p0')
    p0 = source.p0;
else
    p0 = zeros(Nx, Ny, Nz);
end

% make sure the medium parameters are given as matrices
if numel(c) == 1
    c = c*ones(Nx, Ny, Nz);
end

if numel(rho0) == 1
    rho0 = rho0*ones(Nx, Ny, Nz);
    rho0_sgx = rho0;
    rho0_sgy = rho0;
    rho0_sgz = rho0;
end

if numel(absorb_tau) == 1
    absorb_tau = absorb_tau*ones(Nx, Ny, Nz);
end

if numel(absorb_eta) == 1
    absorb_eta = absorb_eta*ones(Nx, Ny, Nz);
end

% create reduced variables for use with real-to-complex FFT (saves memory)
Nx_r = Nx/2 + 1;
kappa_r = kappa(1:Nx_r, :, :);
ddx_k_shift_pos_r = ddx_k_shift_pos(1:Nx_r);
ddx_k_shift_neg_r = ddx_k_shift_neg(1:Nx_r);
absorb_nabla1_r = absorb_nabla1(1:Nx_r, :, :); 
absorb_nabla2_r = absorb_nabla2(1:Nx_r, :, :);

% create scalar size variables
us_index_size = squeeze(length(us_index));
sensor_mask_index_size = squeeze(length(sensor_mask_ind));
transducer_input_signal_size = squeeze(length(transducer_input_signal));

% =========================================================================
% DATACAST AND SAVING
% =========================================================================

% change all the variables to be in single precision
data_cast = 'single';
for cast_index = 1:length(variable_list)
    eval([variable_list{cast_index} ' = ' data_cast '(' variable_list{cast_index} ');']);
end

% change all the index variables to be in unsigned integers
data_cast = 'uint64';
for cast_index = 1:length(integer_variable_list)
    eval([integer_variable_list{cast_index} ' = ' data_cast '(' integer_variable_list{cast_index} ');']);
end
 
% save the input variables to disk as a MATLAB binary file
tic;
disp('  saving input files to disk...');
variable_list = [variable_list, integer_variable_list];
save(save_to_disk, variable_list{:});   
disp(['  completed in ' num2str(toc) 's']);