function mtl = structuralProperties(self,varargin)
%structuralProperties - Assign structural material properties to the model
%   mtl = structuralProperties(structuralmodel,PROPERTY,VALUE) assigns
%   material properties to a structural model. Structural model supports
%   only isotropic materials, hence each VALUE must be specified as a
%   numeric scalar.
%
%   PROPERTY               VALUE
%-------------------------------------------------------------------------
%   'YoungsModulus'       Young's modulus of the material.
%   'PoissonsRatio'       Poisson's ratio of the material.
%   'MassDensity'         Mass density of the material.
%   'CTE'                 Coefficient of thermal expansion of the material.
%   'HystereticDamping'   Hysteretic (structural) damping coefficient.
%
%  For static analysis, specify Young's modulus and Poisson's ratio.
%  However, if gravitational effects are included in modeling, then mass
%  density is also required. Specify coefficient of thermal expansion if
%  thermal effects are modeled in the static analysis.
%
%  For modal and transient analysis, specify Young's modulus, Poisson's
%  ratio, and mass density.
%
%  mtl = structuralProperties(__,'Face',FACEID) assigns structural material
%  properties for the specified face of a 2-D geometry. FACEID is a positive
%  integer in the range of 1 to structuralmodel.Geometry.NumFaces.
%
%  mtl = structuralProperties(__,'Cell',CELLID) assigns structural material
%  properties for the specified cell of a 3-D geometry. CELLID is a positive
%  integer in the range of 1 to structuralmodel.Geometry.NumCells.
%
%   Example 1: Assign structural material properties for a bimetallic cable.
%
%       structuralmodel = createpde('structural','static-solid');
%       structuralmodel.Geometry = multicylinder([0.01,0.015],0.02);
%       pdegplot(structuralmodel,'CellLabels','on','FaceAlpha',0.4)
%       structuralProperties(structuralmodel,'Cell',1,'YoungsModulus',110E9, ...
%                                                  'PoissonsRatio',0.28);
%       structuralProperties(structuralmodel,'Cell',2,'YoungsModulus',210E9, ...
%                                                  'PoissonsRatio',0.3);
%
%   Example 2: Assign structural properties for a static analysis that
%              includes gravitational effect.
%
%       structuralmodel = createpde('structural','static-solid');
%       gm = importGeometry(structuralmodel,'BracketWithHole.stl');
%       structuralProperties(structuralmodel,'YoungsModulus',210E3, ...
%                                            'PoissonsRatio',0.3,...
%                                            'MassDensity',2.7E-6);
%
%   Example 3: Assign structural properties for a static analysis that
%              includes thermal effect.
%
%       structuralmodel = createpde('structural','static-solid');
%       gm = importGeometry(structuralmodel,'BracketWithHole.stl');
%       structuralProperties(structuralmodel,'YoungsModulus',210E3, ...
%                                            'PoissonsRatio',0.3,...
%                                            'CTE',13.0E-6);
%       structuralBodyLoad(structuralmodel,'Temperature',100);
%
%    See also pde.StructuralModel, pde.StructuralModel/structuralBC
%             pde.StructuralModel/structuralBodyLoad,
%             pde.StructuralModel/structuralBoundaryLoad, 
%             pde.StructuralModel/solve

%    Copyright 2017-2021 The MathWorks, Inc.

narginchk(5,13);
nargoutchk(0,1);

if isempty(self.Geometry)
    error(message('pde:StructuralModel:structuralModelHasNoGeom'));
end

parser = inputParser;
parser.addParameter('Face', [], @pde.EquationModel.isValidEntityID);
parser.addParameter('Cell', [], @pde.EquationModel.isValidEntityID);
parser.addParameter('YoungsModulus', [],@pde.EquationModel.isValidAttributeVal);
parser.addParameter('PoissonsRatio', [],@pde.EquationModel.isValidAttributeVal);
parser.addParameter('MassDensity',[],@pde.EquationModel.isValidAttributeVal);
parser.addParameter('CTE',[],@pde.EquationModel.isValidAttributeVal);
parser.addParameter('HystereticDamping',[],@pde.EquationModel.isValidAttributeVal);

parser.parse(varargin{:});
argsToPass = varargin;
%If a face (for 2-D) or a cell (for 3-D) is not explicitly specified then
%use the same material for all faces and edges.

if self.IsTwoD
    if ~isempty(parser.Results.Cell)
        error(message('pde:StructuralModel:noMtlOnCellFor2D'));
    end
    if isempty(parser.Results.Face)
        argsToPass = [{'Face',1:self.Geometry.NumFaces}, varargin];
    else
        self.isValidEntityID(parser.Results.Face);
        if any(parser.Results.Face > self.Geometry.NumFaces)
            error(message('pde:pdeModel:invalidFaceIndex'));
        end
    end
else
    if ~isempty(parser.Results.Face)
        error(message('pde:StructuralModel:noMtlOnBoundary'));
    end    
    if isempty(parser.Results.Cell)
        argsToPass = [{'Cell',1:self.Geometry.NumCells}, varargin];
    else
        self.isValidEntityID(parser.Results.Cell);
        if any(parser.Results.Cell > self.Geometry.NumCells)
            error(message('pde:pdeModel:invalidCellIndex'));
        end
    end
end

if (contains(self.AnalysisType,{'modal','transient'}))
    if (~isempty(parser.Results.CTE))
        warning(message('pde:StructuralModel:thermalLoadingOnlyInStatic'));
    end
end

if (contains(self.AnalysisType,{'modal','transient','frequency'}))
    if (isempty(parser.Results.MassDensity))
        error(message('pde:StructuralModel:incompleteMtlForDynamics'));
    end
end


if isempty(self.MaterialProperties)
    mtlContainer = pde.StructuralMaterialAssignmentRecords(self);
    mtl = pde.StructuralMaterialAssignment(mtlContainer,argsToPass{:});
    mtlContainer.MaterialAssignments = mtl;
    self.MaterialProperties = mtlContainer;
else
    mtl = pde.StructuralMaterialAssignment(self.MaterialProperties,argsToPass{:});
    self.MaterialProperties.MaterialAssignments(end+1) = mtl;
end


end
