classdef (Sealed) StructuralSEIAssignment  < handle 
% StructuralSEIAssignment - Defines a superelement interface (SEI)
% StructuralSEIAssignment objects are created for each superelement
% interface. 
%
% See also pde.StructuralModel, pde.StructuralModel/structuralSEInterface

% Copyright 2019-2022 The MathWorks, Inc.

properties (SetAccess = private)
    %RegionType - Type of geometric region that defines the superelement interface
    RegionType;    
end

properties
    %RegionID - IDs of the geometric regions that form the superelement interface
    RegionID;    

end


methods
    
    function self = StructuralSEIAssignment(sdmr,varargin)
        self.RecordOwner = sdmr;
        parser = inputParser;
        parser.addParameter('Cell',[],@pde.EquationModel.isValidEntityID);
        parser.addParameter('Face',[],@pde.EquationModel.isValidEntityID);
        parser.addParameter('Edge',[],@pde.EquationModel.isValidEntityID);
        parser.addParameter('Vertex',[],@pde.EquationModel.isValidEntityID);
        parser.addParameter('MPCNodes',[],@pde.EquationModel.isValidEntityID);
        parser.addParameter('Reference',[],@pde.EquationModel.isValidAttributeVal);
        parser.addParameter('Radius',[],@pde.EquationModel.isValidAttributeVal);
        parser.addParameter('MPCRequired',false);
        parser.parse(varargin{:});
        
        if ~isempty(parser.Results.Vertex)
            self.RegionType = 'Vertex';
            self.RegionID = parser.Results.Vertex;
        elseif ~isempty(parser.Results.Edge)
            self.RegionType = 'Edge';
            self.RegionID = parser.Results.Edge;
        elseif ~isempty(parser.Results.Face)
            self.RegionType = 'Face';
            self.RegionID = parser.Results.Face;
        elseif ~isempty(parser.Results.MPCNodes)
            self.RegionType = 'MPCNodes';
            self.RegionID = parser.Results.MPCNodes;
            self.MPCRequired = true; % Enforces MPCs when nodes are specified.
        end
        
        if ~isempty(parser.Results.MPCRequired)
            self.MPCRequired = parser.Results.MPCRequired;
        end
        
        if ~isempty(parser.Results.Radius)
            self.Radius = parser.Results.Radius;
        end
        
        if ~isempty(parser.Results.Reference)
            self.Reference = parser.Results.Reference;
        end
    end
    
end

methods % Setter methods
    function set.RegionType(self, rtype)
        self.RegionType = rtype;
    end
    
    function set.RegionID(self, rids)
        self.RegionID = rids;
    end
    
    function set.MPCRequired(self, val)
        self.MPCRequired = val;
    end
    
    function set.Radius(self, val)
        self.CoefPrecheck(val,'Radius');
        self.Radius = val;
    end
    
    function set.Reference(self, val)
        self.CoefPrecheck(val,'Reference');
        self.Reference = val;
    end
end % end of setter methods



methods(Hidden=true, Access = {?pde.StructuralSEIAssignmentRecords})
    function performSolverPrecheck(self)
        checkValidRegionIDs(self)
    end
end

methods(Hidden=true, Access = private)
    
    
    function checkValidRegionIDs(self)
        inputVertex = [];
        inputEdge = [];
        inputFace = [];
        
        if startsWith("Vertex",self.RegionType,'IgnoreCase',true)
            inputVertex = self.RegionID;
        elseif startsWith("Edge",self.RegionType,'IgnoreCase',true)
            inputEdge = self.RegionID;
        elseif startsWith("Face",self.RegionType,'IgnoreCase',true)
            inputFace = self.RegionID;
        end

        self.RecordOwner.ParentModel.validateRegionID(inputVertex, inputEdge, inputFace)
    end
    
end % Private methods


methods(Static, Access = private)
 
    function ok=CoefPrecheck(coef,coefName)
        if ~isempty(coef)
            validateattributes(coef,{'double'},{'nonnan','nonsparse','real','finite'},coefName);
        end
        ok = true;
    end

    
end

methods(Hidden=true)
    function delete(self)
        if ~isempty(self.RecordOwner) && isvalid(self.RecordOwner)
            self.RecordOwner.delistStructuralSEIAssignments(self);
        end
    end
end

properties (Hidden = true, Access='private')
    RecordOwner;
end

properties (Hidden = true, Access={?pde.StructuralSEIAssignmentRecords,?pde.StructuralModel})
    MPCRequired;
    
    %Reference - Reference coordinates for multipoint constraint definition
    Reference;
    
    %Radius - Radius for multipoint constraint definition
    Radius;
    
    %MPCNodes - Nodes for multipoint constraint definition
    MPCNodes;
end

    
end
