classdef validators

% Copyright 2022-2023 The MathWorks, Inc.

    methods (Static)
        function mustBeDoubleOrFunctionHandle(x)
            % also enforces scalar or empty size and finite doubles
            if isa(x,'double')
                mustBeScalarOrEmpty(x);
                mustBeFinite(x);
                mustBeReal(x);
                mustBeNonsparse(x);
            else
                mustBeA(x,{'function_handle','double'}); % double here for a nicer error message
            end
        end

        function mustBePositiveOrFunctionHandle(x)
            % also enforces scalar or empty size and finite doubles
            if isa(x,'double')
                mustBeScalarOrEmpty(x);
                mustBeFinite(x);
                mustBeReal(x);
                mustBePositive(x);
                mustBeNonsparse(x);
            else
                mustBeA(x,{'function_handle','double'}); % double here for a nicer error message
            end
        end

        function mustBeFarField(x)
            % also accept []
            mustBeScalarOrEmpty(x);
            mustBeNonsparse(x);
            if isa(x,'double') && ~isempty(x)
                error(message('pde:ElectromagneticModel:invalidValue','farFieldBC'));
            end
            mustBeA(x,{'double','farFieldBC'});
        end

        function mustBeDoubleVectorOrFunctionHandle(x)
            % also enforces scalar or empty size and finite doubles
            if isa(x,'double')
                mustBeVector(x,'allow-all-empties');
                mustBeFinite(x);
                mustBeReal(x);
                mustBeNonsparse(x);
            else
                mustBeA(x,{'function_handle','double'}); % double here for a nicer error message
            end
        end

        function mustBeVectorOrCellOfDoubles(x)
            mustBeA(x,{'double','cell'});
            if isa(x,'double')
                mustBeVector(x);
                mustBeFinite(x);
                mustBeReal(x);
                mustBeNonsparse(x);
            else
                for i = 1:numel(x)
                    mustBeNumeric(x{i})
                    mustBeVector(x{i});
                    mustBeFinite(x{i});
                    mustBeReal(x{i});
                    mustBeNonsparse(x{i});
                end
            end
        end




        function mustBeNonNegativeDoubleVectorOrFunctionHandle(x)
            % also enforces scalar or empty size and finite doubles
            if isa(x,'double') && ismatrix(x)
                mustBeFinite(x);
                mustBeReal(x);
                mustBeNonsparse(x);
                mustBeNonnegative(x);
            else
                 % For function handles in 1x3 arrays
                mustBeA(x,{'function_handle','double'}); % double here for a nicer error message
            end
        end

        function mustBePositiveDoubleVectorOrFunctionHandle(x)
            % also enforces scalar or empty size and finite doubles
            if isa(x,'double') && ismatrix(x)
                mustBeFinite(x);
                mustBeReal(x);
                mustBeNonsparse(x);
                mustBePositive(x);
            else
                 % For function handles in 1x3 arrays
                mustBeA(x,{'function_handle','double'}); % double here for a nicer error message
            end
        end

        function mustBeDoubleVectorOrFunctionHandleOrComplex(x)
            % also enforces scalar or empty size and finite doubles
            if isa(x,'double')
                mustBeVector(x,'allow-all-empties');
                mustBeFinite(x);
                mustBeNonsparse(x);
            else
                mustBeA(x,{'function_handle','double'}); % double here for a nicer error message
            end
        end        

        function mustBeDoubleOrEmpty(x)
            mustBeScalarOrEmpty(x);
            mustBeA(x,'double');
            mustBeFinite(x);
            mustBeReal(x);
            mustBeNonsparse(x);
        end

        function mustBeDoubleVectorOrEmpty(x)
            mustBeVector(x,'allow-all-empties');
            mustBeA(x,'double');
            mustBeFinite(x);
            mustBeReal(x);
            mustBeNonsparse(x);
        end

        function mustBePositiveOrEmpty(x)
            mustBeScalarOrEmpty(x);
            mustBeA(x,'double');
            mustBeFinite(x);
            mustBeReal(x);
            mustBePositive(x);
            mustBeNonsparse(x);
        end

        function mustBeNonNegativeOrEmpty(x)
            mustBeScalarOrEmpty(x);
            mustBeA(x,'double');
            mustBeFinite(x);
            mustBeReal(x);
            mustBeNonnegative(x);
            mustBeNonsparse(x);
        end

        function mustBeDoubleOrInRange(x,lowval,highval,optstring)
            if isa(x,'double')
                mustBeScalarOrEmpty(x);
                mustBeA(x,'double');
                mustBeFinite(x);
                mustBeReal(x);
                mustBeInRange(x,lowval,highval,optstring);
                mustBeNonsparse(x);
            else
                mustBeA(x,{'function_handle','double'}); % double here for a nicer error message
            end
        end
        % Function created to handle Poisson ratio vector for Orthotropic
        % Materials. Value consistency check deferred to the
        % performSolverPrechecks part in solve.m
        function mustBePoissonRatio(x,lowval,highval,optstring)
            if isa(x,'double')
                if isscalar(x) % isotropic case,where nu > 0 and < 0.5
                    mustBeScalarOrEmpty(x);
                    mustBeReal(x);
                    mustBeInRange(x,lowval,highval,optstring);
                    mustBeNonsparse(x);
                else % Only check for basic input consistency if x is a vector.
                    mustBeVector(x,'allow-all-empties');
                    mustBeA(x,'double');
                    mustBeFinite(x);
                    mustBeReal(x);
                    mustBeNonsparse(x);
                end
            else
                mustBeA(x,{'function_handle','double'}); % double here for a nicer error message
            end
        end

        function mustBeDoubleOrFunctionHandleOrComplex(x)
            % also enforces scalar or empty size and finite doubles
            if isa(x,'double')
                mustBeScalarOrEmpty(x);
                mustBeFinite(x);
                mustBeNonsparse(x);
            else
                mustBeA(x,{'function_handle','double'}); % double here for a nicer error message
            end
        end

        function mustBeCurrentDensity(x)
            if ~(isa(x,'pde.ConductionResults'))
                 if (isa(x,'double') && isvector(x) )|| isempty(x)            
                    if (~isa(x,"function_handle"))
                        mustBeFinite(x);
                        mustBeNonsparse(x);
                    end
                 else
                    mustBeA(x,{'double','function_handle','pde.ConductionResults'});
                 end
            end
        
        end

        function mustBeDisplacement(x)
            % also accept []
            if ~(isa(x,'pde.StaticStructuralResults') || isa(x,'pde.TransientStructuralResults'))
                if ( isvector(x) && isa(x,'double') ) || isempty(x)     
                    if (~isa(x,"function_handle"))
                        mustBeFinite(x);
                        mustBeReal(x);
                        mustBeNonsparse(x);
                    end
                else
                    mustBeA(x,{'double','function_handle','pde.StaticStructuralResults',...
                              'pde.TransientStructuralResults'});
                end

            end

        end

        function mustBeVelocity(x)
            % also accept []
            if ~(isa(x,'pde.StaticStructuralResults')|| isa(x,'pde.TransientStructuralResults'))
                if (isvector(x) && isa(x,'double') ) || isempty(x)
                    if (~isa(x,"function_handle"))
                        mustBeFinite(x);
                        mustBeReal(x);
                        mustBeNonsparse(x);
                    end
                else
                    mustBeA(x,{'double','function_handle','pde.StaticStructuralResults',...
                            'pde.TransientStructuralResults'});
                end
            end
        end

        function mustBeTemperature(x)
            % also accept []
            if ~(isa(x,'pde.TransientThermalResults')||isa(x,'pde.SteadyStateThermalResults'))
                 if (isa(x,'double') && isscalar(x) )|| isempty(x)            
                    if (~isa(x,"function_handle"))
                        mustBeFinite(x);
                        mustBeReal(x);
                        mustBeNonsparse(x);
                    end
                 else
                    mustBeScalarOrEmpty(x);
                    mustBeA(x,{'double','function_handle','pde.TransientThermalResults',...
                        'pde.SteadyStateThermalResults'});
                 end
            end
        end

        function mustBeMagneticVectorPotential(x)
            if ~(isa(x,'pde.MagnetostaticResults'))
                 if (isa(x,'double') && isvector(x))|| isempty(x)            
                    if (~isa(x,"function_handle"))
                        mustBeFinite(x);
                        mustBeReal(x);
                        mustBeNonsparse(x);
                    end
                 else
                    mustBeA(x,{'double','function_handle','pde.MagnetostaticResults'});
                 end
            end
        end

        function mustBeMemberCaseInsensitive(input,options)
            mustBeMember(lower(input), lower(options));
        end
    end

end
