def two_bars(self, young, density, area, length): X = torch.tensor([[0, 0], [length, 0], [length, length]]) conn = torch.tensor([[0, 1], [1, 2]], dtype=int) nodes = Nodes(X) mat = BasicMaterial(lambda e: young * e, density) els = Truss(conn, nodes, area, mat) return Model(nodes, els)
def nodes(self, seed, length, dim): num_nodes = 3 return Nodes( X=length * torch.rand(num_nodes, dim), u=length * torch.rand(num_nodes, dim), v=length * torch.rand(num_nodes, dim), )
def __init__(self, nodes=None, elements=None, time=0, damping=0): self.nodes = Nodes(nodes) if isinstance(nodes, torch.Tensor) else nodes self.elements = [] if elements is None else [elements] self.loads = [] self.constraints = [] self.damping = damping self.time = time
def nodes(self, seed, length, angle, rand_strain): """Three nodes mirrored vertically.""" origin = length * 100 * torch.rand(2) p1 = origin + torch.tensor([length * cos(angle), length * sin(angle)]) p2 = origin + torch.tensor([length * cos(angle), -length * sin(angle)]) X = torch.stack([origin, p1, p2]) # logitudinal stretch u1 = rand_strain * (X[1] - X[0]) u2 = rand_strain * (X[2] - X[0]) u = torch.stack([torch.zeros(2), u1, u2]) return Nodes(X, u)
def pyramid_truss(self, length, area, young, density=1): X = torch.tensor([[0, 0, 0], [0, 1, 0], [1, 1, 0], [1, 0, 0], [1, 1, 1]]) X = (X + 100.0) * length u = torch.rand(8, 3) * length / 2.0 v = torch.rand(8, 3) * length / 2.0 nodes = Nodes(X, u, v) conn = torch.tensor( [[0, 1], [1, 2], [2, 3], [3, 0], [0, 2], [1, 4], [2, 4], [3, 4]], dtype=int, ) material = BasicMaterial(lambda e: young * e, density) elements = Truss(conn, nodes, area, material) model = Model(nodes, elements) # zero damping return model
def test_single_bar_force(self, length, area, young, rtol): # assign a random initial position and normalize to length X = torch.rand((2, 3)) + 100 X = length * X / (X[1] - X[0]).norm() # align the bar to z direction and stretch it strain = 0.1 u = torch.stack([ torch.zeros(3), X[0] - X[1] + length * torch.tensor([0, 0, 1 + strain]) ]) nodes = Nodes(X, u) mat = BasicMaterial(lambda e: young * e) conn = torch.tensor([[0, 1]], dtype=int) elements = Truss(conn, nodes, area, mat) model = Model(nodes, elements) assert model.force()[1, 2] == pytest.approx(-strain * young * area, rel=rtol)
def nodes(self): return Nodes(torch.rand(3, 2))
def test_default_state(self): nodes = Nodes(torch.rand(10, 2)) assert nodes.X.size() == nodes.u.size() assert nodes.X.size() == nodes.v.size() assert torch.allclose(nodes.u, torch.zeros(10, 2)) assert torch.allclose(nodes.v, torch.zeros(10, 2))
def test_current_position(self): nodes = Nodes(torch.rand(10, 2)) assert torch.allclose(nodes.x(), nodes.X) nodes.u = torch.rand(10, 2) assert torch.allclose(nodes.x(), nodes.X + nodes.u)
def test_len(self): nodes = Nodes(torch.rand(10, 2)) assert len(nodes) == 10