function obj = Gzero(m)
%Gzero Default structure for Kronecker Bio objective functions
% 
%   obj = Gzero(m)
%
%  This function is a blank objective function. It is used to fill in the
%  fields with appropriately zero defaults when they are not provided.

% (c) 2010 David R Hagen & Bruce Tidor
% This work is released under the MIT license.

% Special case: return empty structure array if inputs are numeric
if isnumeric(m)
    temp = struct('name', [], 'discreteTimes', [], 'continuous', [], 'complex', [], 'g', [], 'dgdx', [], 'dgdp', [], 'd2gdx2', [], 'd2gdp2', [], 'd2gdxdp', [], 'd2gdpdx', [], 'd3gdx3', [], 'd3gdpdx2', [], 'G', [], 'dGdx', [], 'dGdp', [], 'd2Gdx2', [], 'd2Gdp2', [], 'd2Gdpdx', [], 'd2Gdxdp', [], 'F', [], 'Fn', [], 'p', [], 'pvalue', [], 'n', [], 'AddData', [], 'AddExpectedData', [], 'QuantifyPrediction', [], 'update', []);
    if isempty(m)
        m = 1;
    end
    if ~isscalar(m)
        obj(prod(m),1) = temp;
        obj = reshape(obj, m);
        return
    else
        obj(m,1) = temp;
        return
    end
end

% Gut m
temp = m;
clear m
m.nX = temp.nX;
m.nP = temp.nP;
clear temp

% Objective structure
obj.name = 'unnamed';

% Objective function control parameters
obj.discreteTimes = []; % Times at which discrete measurements are taken
obj.continuous = false; % Continuous g here is 0
obj.complex = false; % This objective function does not need it

% Continuous objective function
obj.g        = @g;
obj.dgdx     = @dgdx;
obj.dgdp     = @dgdp;
obj.d2gdx2   = @d2gdx2;
obj.d2gdp2   = @d2gdp2;
obj.d2gdxdp  = @d2gdxdp;
obj.d2gdpdx  = @d2gdpdx;
obj.d3gdx3   = @d3gdx3;
obj.d3gdpdx2 = @d3gdpdx2;

% Discrete objective function
obj.G = @G;
obj.dGdx = @dGdx;
obj.dGdp = @dGdp;
obj.d2Gdx2 = @d2Gdx2;
obj.d2Gdp2  = @d2Gdp2;
obj.d2Gdpdx = @d2Gdpdx;
obj.d2Gdxdp = @d2Gdxdp;

% Information theory
obj.F = @F;
obj.Fn = @Fn;
obj.p = @p;
obj.pvalue = @pvalue;

% Data manipulation
obj.n = 0; % Number of discrete measurements
obj.AddData = @AddData;
obj.AddExpectedData = @AddExpectedData;
obj.QuantifyPrediction = @QuantifyPrediction;

% Update
obj.update = @Gzero;

    function val = g(t,x,u,nSim)
        val = 0;
    end
    function val = dgdx(t,x,u,nSim)
        val = sparse(1, m.nX);
    end
    function val = dgdp(t,x,u,nSim)
        val = sparse(1, m.nP);
    end
    function val = d2gdx2(t,x,u,nSim)
        val = sparse(m.nX, m.nX);
    end
    function val = d2gdp2(t,x,u,nSim)
        val = sparse(m.nP, m.nP);
    end
    function val = d2gdpdx(t,x,u,nSim)
        val = sparse(m.nX, m.nP);
    end
    function val = d2gdxdp(t,x,u,nSim)
        val = sparse(m.nP, m.nX);
    end
    function val = d3gdx3(t,x,u,nSim)
        val = sparse(m.nX*m.nX, m.nX);
    end
    function val = d3gdpdx2(t,x,u,nSim)
        val = sparse(m.nX*m.nX, m.nP);
    end

    function [val deltaTimes] = G(t,x,u,nSim)
        val = 0;
        deltaTimes = [];
    end
    function val = dGdx(t,x,u,nSim)
        val = sparse(1, m.nX);
    end
    function val = dGdp(t,x,u,nSim)
        val = sparse(1, m.nP);
    end
    function val = d2Gdx2(t,x,u,nSim)
        val = sparse(m.nX, m.nX);
    end
    function val = d2Gdp2(t,x,u,nSim)
        val = sparse(m.nP, m.nP);
    end
    function val = d2Gdpdx(t,x,u,nSim)
        val = sparse(m.nX, m.nP);
    end
    function val = d2Gdxdp(t,x,u,nSim)
        val = sparse(m.nP, m.nX);
    end
    
    function val = F(dxdvSol)
        nT = (size(dxdpSol.y, 1) - m.nX) / m.nX;
        val = zeros(nT,nT);
    end
    function val = Fn(dxdvSol, p)
        nV = (size(dxdpSol.y, 1) - m.nX) / m.nX;
        val = zeros(nT,nT);
    end
    function val = p(sol, u)
        val = 1;
    end
    function val = pvalue(sol, u)
        val = 1;
    end

    function obj = AddData(sol, u)
        obj = Gzero(m);
    end
    function obj = AddExpectedData(sol, u)
        obj = Gzero(m);
    end
    function val = QuantifyPrediction(sol1, sol2, type)
        val = [];
    end

end
