% convergeFrontTestRK: script file to demonstrate RK integrator convergence.
%
% This script file runs through a variety of grid resolutions and (s,p)
%   accuracies to generate empirical convergence plots for frontTestRK
%   example.
%
% Most parameters must be set within frontTestRK, rather than here.

% Copyright 2007 Ian M. Mitchell (mitchell@cs.ubc.ca).
% This software is used, copied and distributed under the licensing 
%   agreement contained in the file LICENSE in the top directory of 
%   the distribution.
%
% Ian Mitchell, 1/4/07

% Where should you get the data?  If you don't do the runs, then load it
% from a file.
run_data = 1;
data_filename = 'errorSpinSquare.WENO5.mat';

% What integrator parameters?
%  We had to remove forward Euler because it is unstable with WENO5.
sources = { 'shu_osher_88', 'shu_osher_88', ...
            'spiteri_ruuth_02', 'spiteri_ruuth_02', ...
            'spiteri_ruuth_02', 'spiteri_ruuth_02', 'spiteri_ruuth_02', ...
            'spiteri_wang_07' };
% Use b+ to denote shu_osher schemes, ro to denote spiteri_ruuth schemes
% that are s = p+2, rx to denote spiteri_ruuth schemes that are s = p+1,
% and ks to denote spiteri_wang schemes.  For p, use : for first order,
% -- for second, - for third and -. for fourth order accurate.
scheme_styles = { 'b--+', 'b-+', ...
                  'r--o', 'r--x', ...
                  'r-o', 'r-x', 'r-.o', ...
                  'k-s' };

ss = { 2, 3, 3, 4, 4, 5, 5, 5 };
ps = { 2, 3, 2, 2, 3, 3, 4, 3 };
cfls = { 1.0, 1.0, 2.0, 3.0, 2.0, 2.65062, 1.50818, 2.5 };
cfl_factor = 0.75;

% Choose a spatial derivative.
derivFunc = @upwindFirstENO3;
derivFunc = @upwindFirstWENO5;

% Choose a shape.
shape = 'rectangle';
%shape = 'circle';
%shape = 'slotted';

% Do you want to do pure rotation, or do you want to add some motion in
% the normal direction so that the shape will grow and then shrink?
add_normal = 0;
%add_normal = 1;

% What resolutions?
%   Note that some fudging will occur (eg, add 1 to get round g.dx).
%resolutions = { 51; 101; 201; 401 };
resolutions = { 51; 101; 201 };

%The remaining stuff should be just about automatic.
num_schemes =  length(sources);
% What schemes to show results for?
show_schemes = 1 : num_schemes;
show_schemes = 1 : 7;                  % Do not plot Spiteri-Wang

scheme_names = cell(size(sources));
for scheme = 1 : num_schemes,
  scheme_names{scheme} = sprintf('source %s, s = %d, p = %d', ...
                                 sources{scheme}, ss{scheme}, ps{scheme});      
end

num_grids = length(resolutions);
min_dx = zeros(num_grids, 1);

err.inf = zeros(num_schemes, num_grids);
err.two = zeros(num_schemes, num_grids);
err.one = zeros(num_schemes, num_grids);


if run_data
  % Get the error data by running frontTestRK.
  for scheme = 1 : num_schemes,

    for resolution = 1 : num_grids;
      
      fprintf('\nGrid Size %d, %s\n', resolutions{resolution}, ...
              scheme_names{scheme});

      % Get the solutions.
      [ data, g, data0, errs ] = frontTestRK(sources{scheme}, ...
                                             ss{scheme}, ps{scheme}, ...
                                             cfl_factor * cfls{scheme}, ...
                                             resolutions{resolution}, ...
                                             derivFunc, shape, add_normal);
      if(min_dx(resolution) == 0)
        min_dx(resolution) = min(g.dx);
      end
    
      % Collect norms.
      err.inf(scheme,resolution) = errs.inf;
      err.two(scheme,resolution) = errs.two;
      err.one(scheme,resolution) = errs.one;
      
    end
  end

else
  % Load the error data from a file.
  load(data_filename);

  % We forgot to save min_dx.  Estimate it (we know that frontTestRK
  % works on domain [ -1, +1 ]).
  for resolution = 1 : num_grids;
    min_dx(resolution) = 2 / (resolutions{resolution} - 1);
  end
end
    
% Plot some results.
gridSizes = cell2mat(resolutions);
errorTypes = fieldnames(err);

for type = 1 : length(errorTypes)
  errorType = errorTypes{type};
  f.(errorType) = figure;
  hold on;

  for scheme = show_schemes,
    errs = err.(errorType);
    h(scheme, type) = plot(gridSizes, errs(scheme,:), scheme_styles{scheme});
  end

  % Escape all occurances of the '_' character so that the TeX
  % interpreter does not screw them up.
  escaped_scheme_names = strrep(scheme_names, '_', '\_');

  % Add in a line showing Delta x.
  h(length(show_schemes) + 1, type) = plot(gridSizes, min_dx, 'k:');
  show_schemes_deltax = [ show_schemes, length(show_schemes) + 1 ];

  % Set the axes so that they include the data (plus some space vertically).
  set(gca, 'XScale', 'log', 'YScale', 'log', 'XTick', gridSizes, ...
           'XGrid', 'on', 'XMinorGrid', 'off', ...
           'YGrid', 'on', 'YMinorGrid', 'off');
  currAxis = axis;
  newAxis = [ min(gridSizes), max(gridSizes), ...
              10^(floor(log10(currAxis(3)))), 10^(ceil(log10(currAxis(4)))) ];
  axis(newAxis);

  % Show slopes with various orders of convergence.
  slopePoint = [ gridSizes(end-2); 100 * newAxis(3) ];
  slopeHandles = addSlopes(slopePoint, ...
                           gridSizes(end-1) - gridSizes(end-2), 'k-', ...
                           [ 0, -1, -2 ], { '', '1', '2' });
%                           [ 0, -2, -4 ], { '', '2', '4' });

  % Label the schemes.
  [ legh, objh ] = legend(h(show_schemes_deltax, type), ...
                          { escaped_scheme_names{show_schemes}, ['\Delta x']});

  % If you did not escape the underscore characters in the scheme names, turn
  % off the TeX interpreter so that sources are not mislabelled.  It seems
  % like the first handle in objh is the text strings, so only work with
  % that one.
  %set(objh(1), 'Interpreter', 'none');

  % Make the lines and markers a bit more visible.
  set(h(show_schemes_deltax, type), 'LineWidth', 2.0, 'MarkerSize', 9.0);

  % Try to make the text a little more visible.
  font_size = 14;
  set(objh(1), 'FontSize', font_size);
  set(gca, 'FontSize', font_size);
  xlabel('Grid Size', 'FontSize', font_size);  
  ylabel('Error', 'FontSize', font_size);
  title([ 'Error analysis for ' errorType ' error.' ], 'FontSize', font_size);  
end
