๐Ÿ’ป Engineering Material Simulation ๐Ÿš€๐Ÿ”ง

# You must make sure to run all cells in sequence using shift + enter or you might encounter errors
from pykubegrader.initialize import initialize_assignment

responses = initialize_assignment("5_classes_q", "week_7", "lecturenotgraded", assignment_points = 21.0, assignment_tag = 'week7-lecturenotgraded')

# Initialize Otter
import otter
grader = otter.Notebook("5_classes_q.ipynb")

๐Ÿ’ป Engineering Material Simulation ๐Ÿš€๐Ÿ”ง#

Problem Statement#

You are designing a Python-based simulation for tracking the stress-strain behavior of different materials under mechanical loading. The simulation should be object-oriented and include the following functionalities:

  1. Class and Instances:

    • Define a class Material to represent different engineering materials.

    • Each material instance should have properties such as name, elastic_modulus, yield_strength, and strain (default: 0.0).

  1. Change Methods with Error Handling:

    • Implement a method apply_strain(self, strain_value: float) to modify the strain.

    • Ensure that the strain does not go below zero and does not exceed a predefined fracture strain (0.05 for all materials). If an invalid strain is applied, raise a ValueError.

  1. Magic Methods:

    • Implement the str magic method to print a readable summary of the material properties.

    • Implement the add method to allow combining two materials into a new CompositeMaterial object with an average of their properties.

  1. Custom Iterator:

    • Create a class MaterialIterator to iterate through a list of materials and return their names one by one.

Task#

Write the Material and MaterialIterator classes, ensuring they adhere to the problem constraints. Then, demonstrate the following:

  • Create instances for Steel and Aluminum.

  • Apply valid and invalid strain values and handle errors appropriately.

  • Print the material properties using str.

  • Combine Steel and Aluminum using + and print the new composite material.

  • Use MaterialIterator to iterate through a list of materials and display their names.

# Step 1: Define the Material class
class Material:

    # Step 2: add the __init__ method to initialize the Material class, with the following parameters:
    # name: (str) Name of the material
    # elastic_modulus: (float) Elastic modulus of the material in GPa
    # yield_strength: (float) Yield strength of the material in MPa
    # assign these parameters to the corresponding class attributes
    # Add placeholders for strain and fracture_strain attributes with default values of 0.0 and 0.05, respectively.
    ...
        """
        ...
        """
        ...

    # Step 3: add the apply_strain method to the Material class, with the following parameters:
    # strain_value: (float) Strain value to apply
    # Check if the strain_value is negative and raise a ValueError with the message "Strain cannot be negative!"
    # Check if the strain_value exceeds the fracture_strain attribute and raise a ValueError with the message "Strain exceeds fracture limit!"
    # If the strain_value is valid, update the strain attribute with the strain_value
    ...
        """
        Apply strain to the material while ensuring it remains within valid limits.
        :param strain_value: Strain value to apply
        """
        ...

    # Step 4: add the __str__ method to the Material class to return a readable string representation of the material.
    # The string should include the name, elastic modulus, yield strength, and current strain of the material.
    # here is an example of the expected output:
    # Material: Steel
    # Elastic Modulus: 200 GPa
    # Yield Strength: 250 MPa
    # Current Strain: 0.0200
    ...
        """
        Magic method to return a readable string representation of the material.
        """
        ...

    # Step 5: add the __add__ method to the Material class to combine two materials into a new composite material.
    # The method should return a new Material instance with averaged properties of the two materials.
    # The name of the composite material should be "Composite(Material1 + Material2)"
    # The elastic modulus and yield strength of the composite material should be the average of the two materials.
    # If the `other`` object is not an instance of Material, raise a TypeError with the message "Can only add another Material instance!"
    ...
        """
        Magic method to combine two materials into a new composite material.
        :param other: Another Material instance
        :return: CompositeMaterial with averaged properties
        """
        # Check if the other object is a Material instance if not return a TypeError with the message "Can only add another Material instance!"
        ...

        # Create a composite material with averaged properties
        # make the composite name as "Composite(Material1 + Material2)"
        ...

        # Calculate the average of elastic modulus and yield strength as composite_modulus and composite_yield_strength
        ...

        # Return a new Material instance with the composite properties
        ...


# Step 2: Define the MaterialIterator class


class MaterialIterator:

    # Step 3: add the __init__ method to initialize the MaterialIterator class, with the following parameters:
    # materials: (list) List of Material instances
    # assign the materials parameter to the materials attribute
    # initialize the index attribute with a value of 0
    ...
        """
        Initialize the iterator with a list of materials.
        :param materials: List of Material instances
        """
        ...

    # Step 4: add the __iter__ method to the MaterialIterator class to return the iterator object itself.
    ...

    # Step 5: add the __next__ method to the MaterialIterator class to return the next material name or stop iteration.
    # If the index is greater than or equal to the length of materials, raise a StopIteration exception.
    # Get the name of the current material using the index attribute.
    # Increment the index by 1 to move to the next material.
    # Return the material name.
    ...


# Step 3: Demonstrate Functionality


# Create instances of materials with name steel with elastic modulus 200 GPa and yield strength 250 MPa
...

# Create another instance of material with name aluminum with elastic modulus 70 GPa and yield strength 150 MPa
...

# Apply valid strain
try:
    steel.apply_strain(0.02)
except ValueError as e:
    print(f"Error: {e}")

# Attempt to apply invalid strain
try:
    aluminum.apply_strain(0.06)  # Exceeds fracture limit
except ValueError as e:
    print(f"Error: {e}")

# Print material properties using __str__
print(steel)
print(aluminum)

# Combine materials using __add__, and save to a new variable `composite``
composite = ...
print(composite)  # Composite material

# Use MaterialIterator to iterate through a list of materials
materials = [steel, aluminum, composite]
iterator = ...

print("\nIterating through materials:")
for material_name in iterator:
    print(material_name)
grader.check("Materials-simulation-classes")

Submitting Assignment#

Please run the following block of code using shift + enter to submit your assignment, you should see your score.

from pykubegrader.submit.submit_assignment import submit_assignment

submit_assignment("week7-lecturenotgraded", "5_classes_q")