function pbeDefinition = checkInputSolver(pbeDefinition)
% check fields in input data that must exist.
%
% THIS IS NO USER FUNCTION.

% The elk-library: convex geometry applied to crystallization modeling.
%   Copyright (C) 2012 Alexander Reinhold
%
% This program is free software: you can redistribute it and/or modify it 
%   under the terms of the GNU General Public License as published by the 
%   Free Software Foundation, either version 3 of the License, or (at your 
%   option) any later version.
%
% This program 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 
%   General Public License for more details.
%
% You should have received a copy of the GNU General Public License along 
%   with this program.  If not, see <http://www.gnu.org/licenses/>.

%% options
if ~isfield(pbeDefinition, 'option')
    pbeDefinition.option = struct();
end


%% time span
if ~isfield(pbeDefinition,'timeSpan')
    error('elk:pbeSolver:wrongInput', ...
        'pbeDefinition must contain a field ''timeSpan''');
end

%% dec
if ~isfield(pbeDefinition,'dec') && (...
        isfield(pbeDefinition, 'seeding') || ...
        isfield(pbeDefinition, 'nucleationRate'))
    error('elk:pbeSolver:wrongInput', ...
        'pbeDefinition must contain a field ''dec'' if seeding or nucleation is used');
elseif ~isfield(pbeDefinition,'dec')
    % use some simple dummy decomposition
    pbeDefinition.dec = obtainCrystalDec('generic_potash_alum', 0);
end

if ~isfield(pbeDefinition, 'nDecCoordinate')
    pbeDefinition.nDecCoordinate = pbeDefinition.dec.nC;
end
if ~isfield(pbeDefinition, 'nExtraCoordinate')
    pbeDefinition.nExtraCoordinate = 0;
end
if ~isfield(pbeDefinition, 'extraZeroBound')
    pbeDefinition.extraZeroBound = [];
elseif size(pbeDefinition.extraZeroBound, 2) ~= pbeDefinition.nExtraCoordinate
    error('elk:pbeSolver:inputError', ['Please correct the number of columns '...
        ' for the extra condition matrix, it must match the number of ' ...
        ' extra property coordinates']);
end


%% growth rate
if ~isfield(pbeDefinition,'growthRate')
    pbeDefinition.growthRate = @(H, P, x, y, t)(H-H);
    pbeDefinition.growthGrad = @(H, P, x, y, t)([]);
else
    if ~isfield(pbeDefinition,'growthGrad')
        pbeDefinition.growthGrad = @(H, P, x, y, t)([]);
    end
end

%% nucleation
if ~isfield(pbeDefinition, 'nucleationRate')
    pbeDefinition.nucleationRate = @(x, y, t)(-1);
    pbeDefinition.nucleationSize = zeros([...
            pbeDefinition.nDecCoordinate + ...
            pbeDefinition.nExtraCoordinate, 1]);
else
    %! Dev: Nucleation cannot be fully supported yet. It was more or less
    %    implemented with a relatively rudimentary scheme analogue to the
    %    moving pivot technique (Kumar, 1997) or Borchert (Thesis, 2012).
    %    This deterministic scheme is currently incompatiple with the
    %    computation of integral properties, but only in a minor extend.
    %    The error estimates would be wrong in that case.
    % This might be resolved by using some probabilistic approach for
    %   introducing pivots and fixing the calculation of integral
    %   properties appropriately. Alternatively, a more rigorous error
    %   estimate might be introduced, given by Briesen 2009 (Escape).
    warning('elk:pbeSolver:wrongInput', ['Handling of nucleation ' ...
        'is not yet fully supported. Calculation of integral properties ' ...
        'will yield wrong error estimated. See more in code comments.']);
    %/
    if ~isfield(pbeDefinition, 'nucleationSize')
        pbeDefinition.nucleationSize = zeros([...
            pbeDefinition.nDecCoordinate + ...
            pbeDefinition.nExtraCoordinate, 1]);
    end
end

%% bulk
if (~isfield(pbeDefinition, 'bulkRate') && ...
     isfield(pbeDefinition, 'bulkInitial')...
     ) || (...
     isfield(pbeDefinition, 'bulkRate') && ...
    ~isfield(pbeDefinition, 'bulkInitial')...
    )
    error('elk:pbeSolver:wrongInput', ...
        'pbeDefinition must contain both fields ''bulkRate'' and ''bulkInitial''');
elseif ~isfield(pbeDefinition, 'bulkRate') && ...
       ~isfield(pbeDefinition, 'bulkInitial')
    % apply a dummy bulk rate to keep solver alive in case of nucleation or
    %   delayed seeding
    pbeDefinition.bulkInitial = 0;
    pbeDefinition.bulkRate = @(x, y, t)(1);
end

%% pivot property
if ~isfield(pbeDefinition, 'pivotProperty')
    pbeDefinition.pivotProperty = @(H, up)(H);
elseif ischar(pbeDefinition.pivotProperty) || ...
       iscell(pbeDefinition.pivotProperty)
   
   pbeDefinition.pivotProperty = @(H, up)(computeMeasureDec(...
       pbeDefinition.dec, 'hC', {up, H}, ...
       pbeDefinition.pivotProperty, [], 0, 1));
end

%% bulk property
if ~isfield(pbeDefinition, 'bulkProperty')
    pbeDefinition.bulkProperty = @(P, N, x, t)([]);
end

%% seeding
if ~isfield(pbeDefinition, 'seeding')
    pbeDefinition.seeding = struct('');
end
