function validReq = linearizeInput(self,label)
%LINEARIZEINPUT  Specify inputs to linearized model.
%
%   LINEARIZEINPUT and LINEARIZEOUTPUT are used in conjunction with
%   LINEARIZE to extract sparse linear models from thermal PDE models.
%
%   LINEARIZEINPUT(pdemodel,LABELSTR) adds a scalar input for the
%   boundary condition with label LABELSTR. This input represents the
%   uniform forcing value applied at this boundary. You must first attach 
%   the label LABELSTR to some heat source (internalHeatSource) or thermal 
%   boundary condition (thermalBC).
%
%   IN = LINEARIZEINPUT(...) returns a structure IN with the linearization 
%   input description.
%
%   Example:
%      tmodel = createpde('thermal','transient');
%      geometryFromEdges(tmodel,@crackg);
%      thermalProperties(tmodel,'ThermalConductivity',1,...
%                            'MassDensity',1,'SpecificHeat',1);
% 
%      thermalBC(tmodel,'Edge',1,'HeatFlux',-10,'Label','Flux');
%      internalHeatSource(tmodel,25,'Label','HeatSource');
%      % Create inputs for heat flux and heat source
%      linearizeInput(tmodel,'Flux');
%      linearizeInput(tmodel,'HeatSource');
%
%   See also pde.ThermalModel/linearizeOutput, pde.ThermalModel/linearize, 
%            pde.ThermalModel/internalHeatSource, pde.ThermalModel/thermalBC.

%    Copyright 2021 The MathWorks, Inc.

arguments
    self pde.ThermalModel
    label {mustBeTextScalar}
end

userReq=label;

if ~isempty(self.BoundaryConditions)
    numBC=numel(self.BoundaryConditions.ThermalBCAssignments);
else
    numBC=0;
end

if ~isempty(self.HeatSources)
    numSource=numel(self.HeatSources.HeatSourceAssignments);
else
    numSource=0;
end

if isequal(numBC,0) && isequal(numSource,0)

    error(message('pde:linearize:NonExistingLabel',userReq));

elseif ~isequal(numBC,0) && isequal(numSource,0)

    bc=findThermalBC(self.BoundaryConditions,'Label',userReq);
    bc=validateBC(bc);
    [labelReq,validReq]=setLabels(bc,self,userReq);
elseif isequal(numBC,0) && ~isequal(numSource,0)

    hss=findHeatSource(self.HeatSources,'Label',userReq);
    [labelReq,validReq]=setLabels(hss,self,userReq);

else
    bc=self.BoundaryConditions;
    hss=self.HeatSources;

    %Assume the label exist in both BC and heat source
    bcFound  = true;
    sourceFound = true;

    %If the label doesn't exist in BC records, set bcFound to false.
    try
        activeInput=findThermalBC(bc,'Label',userReq);
    catch ME
        if strcmp(ME.identifier,'pde:linearize:NonExistingLabel')
            bcFound=false;
        end
    end
    
    % If the label doesn't exist in source records, set sourceFound to false.
    try
        activeInput=findHeatSource(hss,'Label',userReq);
    catch ME
        if strcmp(ME.identifier,'pde:linearize:NonExistingLabel')
            sourceFound=false;
        end
    end

    %Error if the label exists in both BC and heat source
    if bcFound && sourceFound
        error(message('pde:linearize:ThermalLabel',userReq));
    elseif ~(bcFound || sourceFound)
    %Error if the label is not found in either BC or heat source
        error(message('pde:linearize:NonExistingLabel',userReq));
    else
    %Valid case if the label exists in either BC or heat source    
        bc=validateBC(activeInput);
        [labelReq,validReq]=setLabels(bc,self,userReq);
    end
end

self.LinearizeInputs=labelReq;
end

function [labelReq,validReq]=setLabels(bc,self,userReq)


labelReq=self.LinearizeInputs;
validReq=struct('RegionType',bc.RegionType,'RegionID',bc.RegionID,...
    'Label',bc.Label);
if isempty(labelReq)
    labelReq= validReq;
else
    if any(ismember({labelReq.Label},userReq))
        error(message('pde:linearize:RepeatedInput',userReq));
    end
    labelReq(end+1)=validReq;
end
end

function bc=validateBC(activeBC)
if isprop(activeBC,'Temperature')
    invalidNVPair={'ConvectionCoefficient','AmbientTemperature','Emissivity'};
    exist=[~isempty(activeBC.ConvectionCoefficient),~isempty(activeBC.AmbientTemperature),~isempty(activeBC.Emissivity)];
    
    if any(exist)
        idx=find(exist);
        invalidNVPair=invalidNVPair{idx(1)};
        error(message('pde:linearize:nonSupportedNVPairs',invalidNVPair));
    end
    
    NV={'Temperature','HeatFlux'};
    fh=[isa(activeBC.Temperature,'function_handle') isa(activeBC.HeatFlux,'function_handle')];
    if any(fh)
        NV=NV(fh);
        error(message('pde:linearize:nonConstantVal',NV{:}));
    end
else
    if isa(activeBC.HeatSource,'function_handle')
        error(message('pde:linearize:nonConstantVal','HeatSource'));
    end
end
bc=activeBC;
end