Skip to content

Commit

Permalink
Refactor deformation gradient generation and rotation
Browse files Browse the repository at this point in the history
  • Loading branch information
jpsferreira committed Mar 14, 2024
1 parent 8eded59 commit 2a72242
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 24 deletions.
54 changes: 50 additions & 4 deletions hyper_surrogate/deformation_gradient.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ class DeformationGradient:
def __init__(self) -> None:
pass

def __repr__(self) -> str:
return "DeformationGradient"

def __str__(self) -> str:
return "DeformationGradient"

def __call__(self) -> str:
return "DeformationGradient"

@staticmethod
def uniaxial(stretch: np.ndarray) -> np.ndarray:
stretch = np.atleast_1d(stretch)
Expand Down Expand Up @@ -81,10 +90,10 @@ def _axis_rotation(axis: int, angle: float) -> np.ndarray:

def rotation(self, axis: np.ndarray, angle: np.ndarray) -> np.ndarray:
axis, angle = np.atleast_1d(axis), np.atleast_1d(angle)
rotations = []
rotation = []
for ax, ang in zip(axis, angle):
rotations.append(self._axis_rotation(ax, ang))
return np.array(rotations)
rotation.append(self._axis_rotation(ax, ang))
return np.array(rotation)

def rescale(self, F: np.ndarray) -> Any:
return F / self.invariant3(F) ** (1.0 / 3.0)
Expand All @@ -105,6 +114,10 @@ def invariant3(F: np.ndarray) -> Any:
def to_radians(degree: float) -> float:
return degree * np.pi / 180

@staticmethod
def rotate(F: np.ndarray, R: np.ndarray) -> Any:
return np.matmul(np.matmul(R, F), R.T)


class DeformationGradientGenerator(DeformationGradient):
def __init__(
Expand All @@ -124,7 +137,40 @@ def angle(self, min_interval: float = 5) -> Any:
min_interval = self.to_radians(min_interval)
return self.generator.float_in_interval(a=0, b=np.pi, interval=min_interval)

def rotate(self, n_axis: int = 3, min_interval: float = 5) -> np.ndarray:
def generate_rotation(self, n_axis: int = 3, min_interval: float = 5) -> np.ndarray:
axis = self.axis(n_axis=n_axis)
angle = self.angle(min_interval=min_interval)
return self.rotation(axis, angle)

def generate(
self,
stretch_min: float = 0.4,
stretch_max: float = 3.0,
shear_min: float = -1,
shear_max: float = 1,
) -> Any:
u, s, b1, b2 = (
self.generator.uniform(stretch_min, stretch_max),
self.generator.uniform(shear_min, shear_max),
self.generator.uniform(stretch_min, stretch_max),
self.generator.uniform(stretch_min, stretch_max),
)
fu, fs, fb = (
self.uniaxial(u),
self.shear(s),
self.biaxial(b1, b2),
)
r1, r2, r3 = (
self.generate_rotation(),
self.generate_rotation(),
self.generate_rotation(),
)

# rotate deformation gradients
fu = self.rotate(fu, r1)
fs = self.rotate(fs, r2)
fb = self.rotate(fb, r3)

# Compute deformation gradient
F = np.matmul(np.matmul(fb, fu), fs)
return F
14 changes: 7 additions & 7 deletions tests/test_deformation_gradient.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,26 +51,26 @@ def test_to_radians_method(self):

# can generate a random deformation gradient without errors
def test_generate_random_deformation_gradient(self, deformation_generator):
deformation_gradient = deformation_generator.rotate()
deformation_gradient = deformation_generator.generate_rotation()
assert isinstance(deformation_gradient, np.ndarray)

# n_axis=1 generates deformation gradients with zeros
def test_n_axis_1_generates_eye(self, deformation_generator):
np.random.seed(0)
result = deformation_generator.rotate(n_axis=1)
result = deformation_generator.generate_rotation(n_axis=1)
expected = np.array([[[1, 0, 0], [0, 1, 0], [0, 0, 1]]])
assert np.array_equal(result, expected)

# n_axis=4 generates deformation gradients with zeros
def test_n_axis_4_generates_eye(self, deformation_generator):
np.random.seed(0)
deformation_gradient = deformation_generator.rotate(n_axis=4)
deformation_gradient = deformation_generator.generate_rotation(n_axis=4)
assert np.all(deformation_gradient == np.eye(3))

# can generate multiple random deformation gradients without errors
def test_generate_multiple_random_deformation_gradients(self, deformation_generator):
for _ in range(10):
deformation_gradient = deformation_generator.rotate()
deformation_gradient = deformation_generator.generate_rotation()
assert isinstance(deformation_gradient, np.ndarray)
for _ in range(10):
deformation_gradient = deformation_generator.uniaxial(2.0)
Expand All @@ -88,18 +88,18 @@ def test_generate_multiple_random_deformation_gradients(self, deformation_genera
# min_interval=180 generates deformation gradients with eye matrix
def test_min_interval_180_generates_eye(self, deformation_generator):
deformation_generator.seed = 12345
deformation_gradient = deformation_generator.rotate(n_axis=1, min_interval=180)
deformation_gradient = deformation_generator.generate_rotation(n_axis=1, min_interval=180)
assert np.all(deformation_gradient - np.eye(3) < 1e-10)

# min_interval=0 generates deformation gradients with eye matrix
def test_min_interval_zero_generates_eye(self, deformation_generator):
deformation_generator.seed = 0
deformation_gradient = deformation_generator.rotate(n_axis=1, min_interval=0)
deformation_gradient = deformation_generator.generate_rotation(n_axis=1, min_interval=0)
assert np.all(deformation_gradient == np.eye(3))

# can generate deformation gradients with negative values
def test_generate_deformation_gradients_with_negative_values(self, deformation_generator):
deformation_gradient = deformation_generator.rotate(
deformation_gradient = deformation_generator.generate_rotation(
n_axis=1,
)
assert np.any(deformation_gradient < 0)
19 changes: 12 additions & 7 deletions tests/test_generate_deformation_gradient.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import numpy as np
import pytest

from hyper_surrogate.deformation_gradient import DeformationGradientGenerator
from hyper_surrogate.generator import Generator


@pytest.fixture
def def_gradient():
return DeformationGradientGenerator(seed=42, size=10)


@pytest.fixture
def generator():
return Generator(seed=42, size=10)
def test_generate_def_grad(def_gradient):
stretch = def_gradient.generator.uniform(0, 1)
assert len(stretch) == 10
assert all(isinstance(x, float) for x in stretch)
assert all(0 <= x <= 1 for x in stretch)
assert isinstance(stretch, np.ndarray)
assert isinstance(stretch[0], float)
assert isinstance(stretch[1], float)


# def test_generate_def_grad(def_gradient):
# stretch = def_gradient.generate.uniform(1, 2)
# logging.info(f"Stretch: {def_gradient.shear([2,1])}")
# def test_generate_10_def_grad(def_gradient):
# logging.info("Testing 10 deformation gradients")
# logging.info(def_gradient.generate())
6 changes: 0 additions & 6 deletions tests/test_random_deformation_gradient.py

This file was deleted.

0 comments on commit 2a72242

Please sign in to comment.