Skip to content

Commit

Permalink
add docstring
Browse files Browse the repository at this point in the history
  • Loading branch information
obouchaara committed Jun 19, 2024
1 parent b863264 commit fff3df9
Show file tree
Hide file tree
Showing 3 changed files with 186 additions and 26 deletions.
32 changes: 32 additions & 0 deletions src/mechpy/core/symbolic/elasticity.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,33 @@


class SymbolicLinearElasticity:
"""
A class used to represent symbolic linear elasticity computations.
Methods
-------
hookes_law(compliance_tensor, stress_tensor)
Computes the strain tensor from the compliance tensor and the stress tensor.
hookes_law_inverse(stiffness_tensor, strain_tensor)
Computes the stress tensor from the stiffness tensor and the strain tensor.
"""

@staticmethod
def hookes_law(
compliance_tensor: SymbolicComplianceTensor,
stress_tensor: SymbolicStressTensor,
) -> SymbolicStrainTensor:
"""
Computes the strain tensor from the compliance tensor and the stress tensor using Hooke's Law.
:param compliance_tensor: SymbolicComplianceTensor
The compliance tensor of the material.
:param stress_tensor: SymbolicStressTensor
The stress tensor.
:return: SymbolicStrainTensor
The computed strain tensor.
"""
strain_tensor = compliance_tensor @ stress_tensor
return strain_tensor

Expand All @@ -19,5 +41,15 @@ def hookes_law_inverse(
stiffness_tensor: SymbolicStiffnessTensor,
strain_tensor: SymbolicStrainTensor,
) -> SymbolicStressTensor:
"""
Computes the stress tensor from the stiffness tensor and the strain tensor using the inverse of Hooke's Law.
:param stiffness_tensor: SymbolicStiffnessTensor
The stiffness tensor of the material.
:param strain_tensor: SymbolicStrainTensor
The strain tensor.
:return: SymbolicStressTensor
The computed stress tensor.
"""
stress_tensor = stiffness_tensor @ strain_tensor
return stress_tensor
93 changes: 67 additions & 26 deletions src/mechpy/core/symbolic/field.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,23 @@


class SymbolicField:
def __init__(self, coord_system, data, field_params=None, symbols_validation=True):
"""
Initialize a SymbolicField instance.
"""
Represents a symbolic field in a given coordinate system.
:param coord_system: The coordinate system for the field.
:type coord_system: SymbolicCoordSystem
:param data: The field data.
:type data: sp.NDimArray
:param field_params: Additional field parameters. Defaults to {}.
:type field_params: dict, optional
:param symbols_validation: If True, validate symbols in the field data. Defaults to True.
:type symbols_validation: bool
:raises ValueError: If coord_system is not a SymbolicCoordSystem, data is not a NDimArray,
or if field parameters overlap with coordinate system basis symbols.
"""

:param coord_system: The coordinate system for the field.
:type coord_system: SymbolicCoordSystem
:param data: The field data.
:type data: sp.MutableDenseNDimArray
:param field_params: Additional field parameters. Defaults to {}.
:type field_params: dict, optional
:raises ValueError: If coord_system is not a SymbolicCoordSystem, data is not a MutableDenseNDimArray,
or if field parameters overlap with coordinate system basis symbols.
"""
def __init__(self, coord_system, data, field_params=None, symbols_validation=True):
if not isinstance(coord_system, SymbolicCoordSystem):
raise ValueError("Coord system must be a SymbolicCoordSystem.")

Expand Down Expand Up @@ -58,12 +61,19 @@ def __init__(self, coord_system, data, field_params=None, symbols_validation=Tru
def __repr__(self):
return f"{self.__class__.__name__}(\n{self.coord_system.basis},\n{self.data},\n{self.field_params})"

def get_invalid_symbols(self):
def get_invalid_symbols(self) -> set:
"""
Get symbols in the field data that are not in the basis or field parameters.
:return: A set of invalid symbols.
:rtype: set
"""

def get_ignored_symbols(data):
symbols_set = set()
# to implement
return symbols_set

basis = set(self.coord_system.basis)
field_param = set(self.field_params)
valid_symbols = basis.union(field_param)
Expand All @@ -76,16 +86,18 @@ def get_ignored_symbols(data):
def subs_field_params(self, param_values):
"""
Substitute the provided field parameters with specific values, and
remove them from self.field_params. Raise an error if a parameter in
param_values is not in self.field_params.
remove them from self.field_params.
:param param_values: A dictionary mapping parameters to their values.
:type param_values: dict
:raises TypeError: If param_values is not a dictionary.
:raises ValueError: If a parameter in param_values is not in self.field_params.
:return: None. The method updates self.data and self.field_params in place.
"""
if not isinstance(param_values, dict):
raise TypeError("param_values must be a dictionary")

# Perform the substitution for provided parameters
for param, value in param_values.items():
if not param in self.field_params:
raise ValueError(f"Parameter {param} not found in field parameters")
Expand All @@ -97,14 +109,14 @@ def to_cartesian(self):
"""
Converts the scalar field from its current coordinate system
(cylindrical or spherical) to the Cartesian coordinate system.
:raises ValueError: If the current coordinate system is not cylindrical or spherical.
:return: A new SymbolicField in the Cartesian coordinate system.
:rtype: SymbolicField
"""
if not isinstance(
self.coord_system,
(
SymbolicCylindricalCoordSystem,
SymbolicSphericalCoordSystem,
),
):
coord_classes = (SymbolicCylindricalCoordSystem, SymbolicSphericalCoordSystem)
if not isinstance(self.coord_system, coord_classes):
raise ValueError(
"Conversion to Cartesian is only implemented for cylindrical and spherical coordinate systems."
)
Expand All @@ -116,6 +128,15 @@ def to_cartesian(self):
)

def to_cylindrical(self):
"""
Converts the scalar field from its current coordinate system
(Cartesian) to the cylindrical coordinate system.
:raises NotImplementedError: If the current coordinate system is not Cartesian.
:return: A new SymbolicField in the cylindrical coordinate system.
:rtype: SymbolicField
"""
if not isinstance(self.coord_system, SymbolicCartesianCoordSystem):
raise NotImplementedError(
"Conversion from non-Cartesian systems is not implemented"
Expand All @@ -128,6 +149,15 @@ def to_cylindrical(self):
)

def to_spherical(self):
"""
Converts the scalar field from its current coordinate system
(Cartesian) to the spherical coordinate system.
:raises NotImplementedError: If the current coordinate system is not Cartesian.
:return: A new SymbolicField in the spherical coordinate system.
:rtype: SymbolicField
"""
if not isinstance(self.coord_system, SymbolicCartesianCoordSystem):
raise NotImplementedError(
"Conversion from non-Cartesian systems is not implemented"
Expand All @@ -138,6 +168,11 @@ def to_spherical(self):
return self.__class__(spherical_coord_system, spherical_data, self.field_params)

def subs(self, subs_dict, keys=False):
"""
Deprecated method for substituting values. Raises a warning.
:raises DeprecationWarning: This method is deprecated.
"""
raise DeprecationWarning


Expand Down Expand Up @@ -283,7 +318,13 @@ class SymbolicVectorField(SymbolicSpatialField):
shape = (3,)

@classmethod
def create(cls, coord_system=None, data=None, field_params=None, symbols_validation=True):
def create(
cls,
coord_system=None,
data=None,
field_params=None,
symbols_validation=True,
):
if data is None:
if coord_system is None:
coord_system = SymbolicCartesianCoordSystem()
Expand Down
87 changes: 87 additions & 0 deletions src/mechpy/core/symbolic/material.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,81 @@


class SymbolicComplianceTensor(SymbolicSixBySixTensor):
"""
Represents the compliance tensor used in elasticity calculations.
:param data: The tensor data.
:param name: The name of the tensor.
"""
def __init__(self, data, name=None):
super().__init__(data, name)


class SymbolicStiffnessTensor(SymbolicSixBySixTensor):
"""
Represents the stiffness tensor used in elasticity calculations.
:param data: The tensor data.
:param name: The name of the tensor.
"""
def __init__(self, data, name=None):
super().__init__(data, name)


class SymbolicMaterial:
"""
Represents a general material with symbolic properties.
:param material_props: Arbitrary keyword arguments representing material properties.
"""
def __init__(self, **material_props):
for k, v in material_props.items():
setattr(self, k, v)

def __repr__(self):
"""
Returns a string representation of the material and its properties.
:return: String representation of the material.
"""
props = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())
return f"{self.__class__.__name__}({props})"


class SymbolicElasticMaterial(SymbolicMaterial):
"""
Represents an elastic material with methods to compute stiffness and compliance tensors.
:param material_props: Arbitrary keyword arguments representing material properties.
"""
def __init__(self, **material_props):
super().__init__(**material_props)

def stiffness_tensor(self):
"""
Computes the stiffness tensor for the material.
:raises NotImplementedError: This method should be implemented by subclasses.
"""
raise NotImplementedError("Subclasses must implement this method.")

def compliance_tensor(self) -> SymbolicComplianceTensor:
"""
Computes the compliance tensor for the material.
:return: The computed compliance tensor.
"""
components = self.stiffness_tensor().to_matrix().inv()
data = sp.ImmutableDenseNDimArray(components)
return SymbolicComplianceTensor(sp.simplify(data))


class SymbolicIsotropicMaterial(SymbolicElasticMaterial):
"""
Represents an isotropic elastic material with properties such as Young's modulus and Poisson's ratio.
:param material_props: Arbitrary keyword arguments representing material properties.
"""
def __init__(self, **material_props):
keys = material_props.keys()
if not ({"E", "nu"} <= set(keys) or {"lamda", "mu"} <= set(keys)):
Expand All @@ -53,17 +95,37 @@ def __init__(self, **material_props):

@staticmethod
def lame_params(E, nu):
"""
Converts Young's modulus and Poisson's ratio to Lamé parameters.
:param E: Young's modulus.
:param nu: Poisson's ratio.
:return: Tuple of Lamé parameters (lambda, mu).
"""
lamda = (E * nu) / ((1 + nu) * (1 - 2 * nu))
mu = E / (2 * (1 + nu))
return lamda, mu

@staticmethod
def youngs_params(lamda, mu):
"""
Converts Lamé parameters to Young's modulus and Poisson's ratio.
:param lamda: First Lamé parameter.
:param mu: Second Lamé parameter (shear modulus).
:return: Tuple of Young's modulus and Poisson's ratio (E, nu).
"""
E = mu * (3 * lamda + 2 * mu) / (lamda + mu)
mu = lamda / (2 * (lamda + mu))
return E, mu

def stiffness_tensor(self, lames_param=True) -> SymbolicStiffnessTensor:
"""
Computes the stiffness tensor for the isotropic material.
:param lames_param: If True, use Lamé parameters; otherwise, use Young's modulus and Poisson's ratio.
:return: The computed stiffness tensor.
"""
if lames_param and hasattr(self, "lamda") and hasattr(self, "mu"):
lamda, mu = self.lamda, self.mu
elif hasattr(self, "E") and hasattr(self, "nu"):
Expand All @@ -89,6 +151,11 @@ def stiffness_tensor(self, lames_param=True) -> SymbolicStiffnessTensor:
return SymbolicStiffnessTensor(sp.simplify(C))

def compliance_tensor(self) -> SymbolicComplianceTensor:
"""
Computes the compliance tensor for the isotropic material.
:return: The computed compliance tensor.
"""
if hasattr(self, "E") and hasattr(self, "nu"):
E, nu = self.E, self.nu
elif hasattr(self, "lamda") and hasattr(self, "mu"):
Expand Down Expand Up @@ -117,6 +184,11 @@ def compliance_tensor(self) -> SymbolicComplianceTensor:


class SymbolicTransverseIsotropicMaterial(SymbolicElasticMaterial):
"""
Represents a transverse isotropic material with specific elastic properties.
:param material_props: Arbitrary keyword arguments representing material properties.
"""
props_keys = {"E_L", "E_T", "nu", "G_L", "G_T"}

def __init__(self, **material_props):
Expand All @@ -131,6 +203,11 @@ def __init__(self, **material_props):
super().__init__(**material_props)

def stiffness_tensor(self) -> SymbolicStiffnessTensor:
"""
Computes the stiffness tensor for the transverse isotropic material.
:return: The computed stiffness tensor.
"""
E_L = self.E_L
E_T = self.E_T
nu = self.nu
Expand Down Expand Up @@ -158,6 +235,11 @@ def stiffness_tensor(self) -> SymbolicStiffnessTensor:


class SymbolicOrthotropicMaterial(SymbolicElasticMaterial):
"""
Represents an orthotropic material with specific elastic properties.
:param material_props: Arbitrary keyword arguments representing material properties.
"""
props_keys = {"E1", "E2", "E3", "G12", "G23", "G31", "nu12", "nu23", "nu31"}

def __init__(self, **material_props):
Expand All @@ -176,6 +258,11 @@ def __init__(self, **material_props):
super().__init__(**material_props)

def stiffness_tensor(self) -> SymbolicStiffnessTensor:
"""
Computes the stiffness tensor for the orthotropic material.
:return: The computed stiffness tensor.
"""
C11, C22, C33 = self.E1, self.E2, self.E3
C44, C55, C66 = self.G23, self.G31, self.G12
C12 = self.nu12 * C22
Expand Down

0 comments on commit fff3df9

Please sign in to comment.