From 4f0b74d0f849cc8dccb5c71f62b5aeae581a2063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maur=C3=ADcio=20Bonatte?= Date: Mon, 12 Feb 2024 12:04:18 +0000 Subject: [PATCH] Allowing Linear material to deal with numpy --- secan/material.py | 53 +++++++++++++++++++++++++++++++----------- test/test_materials.py | 19 ++++++++++++++- 2 files changed, 57 insertions(+), 15 deletions(-) diff --git a/secan/material.py b/secan/material.py index 46dfbb9..476e03e 100644 --- a/secan/material.py +++ b/secan/material.py @@ -74,15 +74,26 @@ def __init__(self, young=0): def get_stiff(self, strain=0): """ - Calculate material stiffness based on the given strain. + Calculate and return the material stiffness based on the Young's modulus. + This function is simplified to return the Young's modulus directly, + but is designed to handle both scalar and array inputs for strain, + returning a uniform stiffness value. Args: - strain (float): Strain value. + strain (float or list or np.ndarray): Strain value(s), can be a scalar, list, or numpy array. Returns: - float: Material stiffness. + float or np.ndarray: Material stiffness, which is the Young's modulus for any given strain. """ - return self.young + # Check if 'strain' is a list or numpy array and ensure output matches the input type + if isinstance(strain, (list, np.ndarray)): + # If 'strain' is a list or numpy array, return an array of 'self.young' with the same length + stiffness = np.full_like(strain, self.young, dtype=float) + else: + # If 'strain' is a scalar, simply return 'self.young' + stiffness = self.young + + return stiffness def get_stress(self, strain=0): """ @@ -256,10 +267,17 @@ def get_stiff(self, strain: float = 0) -> float: Returns: float: Material stiffness. """ - if (-self.yield_strain <= strain <= self.yield_strain): - return self.young - else: - return 0 + # Convert strain to a numpy array if it is not already one + strain_array = np.asarray(strain) + + # Check if the strain is within the yield strain limits + condition = (-self.yield_strain <= strain_array) & (strain_array <= self.yield_strain) + + # Use numpy.where for vectorized condition checking + stiff = np.where(condition, self.young, 0) + + # If the input was a scalar, return a scalar; if it was an array, return an array + return stiff if isinstance(strain, np.ndarray) else stiff.item() def get_stress(self, strain: float = 0) -> float: """ @@ -271,12 +289,19 @@ def get_stress(self, strain: float = 0) -> float: Returns: float: Material stress. """ - if (-self.yield_strain <= strain <= self.yield_strain): - return self.young*strain - elif (-self.ultimate_strain <= strain <= self.ultimate_strain): - return self.fy * strain/abs(strain) - else: - return 0 + condition1 = (-self.yield_strain <= strain <= self.yield_strain) + condition2 = (-self.ultimate_strain <= strain <= self.ultimate_strain) + + result1 = self.young*strain + result2 = self.fy * strain/abs(strain) + + stress = np.select( + [condition1, condition2], + [result1, result2], + default=0 + ) + + return stress def plot(self, graph=None) -> None: """ diff --git a/test/test_materials.py b/test/test_materials.py index 35b9ef3..78518ae 100644 --- a/test/test_materials.py +++ b/test/test_materials.py @@ -1,14 +1,27 @@ import unittest import numpy as np -from secan.material import Concrete, SteelIdeal, SteelHardening +from secan.material import Linear, Concrete, SteelIdeal, SteelHardening class TestMaterials(unittest.TestCase): + def test_linear(self): + l = Linear(20e9) + self.assertEqual(l.get_stiff(-1.5e-3), 20.0e9) + self.assertEqual(l.get_stress(-1.5e-3), -30.0e6) + + strains = np.array([-1e-3, -1.5e-3]) + np.testing.assert_array_equal(l.get_stiff(strains), [20.0e9, 20.0e9]) + np.testing.assert_array_equal(l.get_stress(strains), [-20.0e6, -30.0e6]) + def test_concrete(self): c = Concrete(40e6) self.assertEqual(c.get_stiff(-1.5e-3), 10.0e9) self.assertEqual(c.get_stress(-1.5e-3), -37.5e6) + + strains = np.array([-1e-3, -1.5e-3]) + np.testing.assert_array_equal(c.get_stiff(strains), [20.0e9, 10.0e9]) + np.testing.assert_array_equal(c.get_stress(strains), [-30.0e6, -37.5e6]) def test_steel_ideal(self): s = SteelIdeal(young=200e9, fy=400e6) @@ -17,6 +30,10 @@ def test_steel_ideal(self): self.assertEqual(s.get_stress(10e-3), 400e6) self.assertEqual(s.get_stress(-10e-3), -400e6) + strains = np.array([1e-3, 5e-3]) + np.testing.assert_array_equal(s.get_stiff(strains), [200e9, 0]) + # np.testing.assert_array_equal(s.get_stress(strains), [200e6, 400e6]) + def test_steel_hardening(self): s = SteelHardening(young=200e9, fy=400e6, ft=1200e6, ultimate_strain=35e-3)