pyMOTO 1.2.0__tar.gz → 1.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/PKG-INFO +1 -1
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/pyMOTO.egg-info/PKG-INFO +1 -1
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/pyMOTO.egg-info/SOURCES.txt +1 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/pymoto/__init__.py +1 -1
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/pymoto/common/domain.py +3 -3
- pyMOTO-1.2.1/tests/test_assembly.py +91 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/LICENSE +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/README.md +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/pyMOTO.egg-info/dependency_links.txt +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/pyMOTO.egg-info/requires.txt +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/pyMOTO.egg-info/top_level.txt +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/pyMOTO.egg-info/zip-safe +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/pymoto/common/dyadcarrier.py +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/pymoto/common/mma.py +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/pymoto/common/solvers.py +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/pymoto/common/solvers_dense.py +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/pymoto/common/solvers_sparse.py +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/pymoto/core_objects.py +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/pymoto/modules/assembly.py +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/pymoto/modules/autodiff.py +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/pymoto/modules/complex.py +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/pymoto/modules/filter.py +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/pymoto/modules/generic.py +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/pymoto/modules/io.py +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/pymoto/modules/linalg.py +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/pymoto/modules/scaling.py +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/pymoto/routines.py +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/pymoto/utils.py +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/pyproject.toml +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/setup.cfg +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/tests/test_automod.py +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/tests/test_complex.py +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/tests/test_core.py +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/tests/test_dyadcarrier.py +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/tests/test_linsolve_sparse.py +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/tests/test_module_concatsignal.py +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/tests/test_module_eigensolve.py +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/tests/test_module_einsum.py +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/tests/test_module_mathgeneral.py +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/tests/test_scaling.py +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/tests/test_solvers_dense.py +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/tests/test_solvers_sparse.py +0 -0
- {pyMOTO-1.2.0 → pyMOTO-1.2.1}/tests/test_static_condenstation.py +0 -0
@@ -184,10 +184,10 @@ class DomainDefinition:
|
|
184
184
|
"""
|
185
185
|
v = np.prod(self.element_size[:self.dim])
|
186
186
|
assert v > 0.0, 'Element volume needs to be positive'
|
187
|
-
|
187
|
+
shapefn = np.ones(self.elemnodes)/v
|
188
188
|
for i in range(self.dim):
|
189
|
-
|
190
|
-
return
|
189
|
+
shapefn *= np.array([self.element_size[i]/2 + n[i]*pos[i] for n in self.node_numbering])
|
190
|
+
return shapefn
|
191
191
|
|
192
192
|
def eval_shape_fun_der(self, pos: np.ndarray):
|
193
193
|
""" Evaluates the shape function derivatives in x, y, and optionally z-direction.
|
@@ -0,0 +1,91 @@
|
|
1
|
+
import unittest
|
2
|
+
import numpy as np
|
3
|
+
import pymoto as pym
|
4
|
+
import numpy.testing as npt
|
5
|
+
|
6
|
+
|
7
|
+
class TestAssembleStiffness(unittest.TestCase):
|
8
|
+
def test_FEA_pure_tensile_2d_one_element(self):
|
9
|
+
Lx, Ly, Lz = 0.1, 0.2, 0.3
|
10
|
+
domain = pym.DomainDefinition(1, 1, unitx=Lx, unity=Ly, unitz=Lz)
|
11
|
+
nodidx_left = domain.get_nodenumber(0, np.arange(domain.nely + 1))
|
12
|
+
# Fixed at bottom, roller at the top in y-direction
|
13
|
+
nodidx_right = domain.get_nodenumber(domain.nelx, np.arange(domain.nely + 1))
|
14
|
+
dofidx_left = np.concatenate([nodidx_left*2, np.array([nodidx_left[0]*2 + 1])])
|
15
|
+
|
16
|
+
E, nu = 210e+9, 0.3
|
17
|
+
|
18
|
+
s_x = pym.Signal('x', state=np.ones(domain.nel))
|
19
|
+
|
20
|
+
# Assemble stiffness matrix
|
21
|
+
m_K = pym.AssembleStiffness(s_x, domain=domain, bc=dofidx_left, e_modulus=E, poisson_ratio=nu, plane='stress')
|
22
|
+
s_K = m_K.sig_out[0]
|
23
|
+
|
24
|
+
m_K.response()
|
25
|
+
F = 1.5
|
26
|
+
f = np.zeros(domain.nnodes*2)
|
27
|
+
f[nodidx_right * 2] = F/nodidx_right.size
|
28
|
+
x = np.linalg.solve(s_K.state.toarray(), f)
|
29
|
+
|
30
|
+
# Bottom y displacement should be zero
|
31
|
+
npt.assert_allclose(x[nodidx_right[0]*2+1], 0, atol=1e-10)
|
32
|
+
|
33
|
+
# Analytical axial displacement using stiffness k = EA/L
|
34
|
+
ux_chk = F * Lx / (E * Ly * Lz)
|
35
|
+
npt.assert_allclose(x[nodidx_right*2], ux_chk, rtol=1e-10)
|
36
|
+
|
37
|
+
# Transverse displacement using Poisson's effect
|
38
|
+
e_xx = ux_chk / Lx # Strain in x-direction
|
39
|
+
e_yy = - nu * e_xx
|
40
|
+
uy_chk = e_yy * Ly
|
41
|
+
npt.assert_allclose(x[nodidx_right[1]*2+1], uy_chk, rtol=1e-10)
|
42
|
+
|
43
|
+
def test_FEA_pure_tensile_3d_one_element(self):
|
44
|
+
Lx, Ly, Lz = 0.1, 0.2, 0.3
|
45
|
+
domain = pym.DomainDefinition(1, 1, 1, unitx=Lx, unity=Ly, unitz=Lz)
|
46
|
+
nodidx_left = domain.get_nodenumber(*np.meshgrid(0, range(domain.nely + 1), range(domain.nelz + 1))).flatten()
|
47
|
+
# Fixed at (0,0,0), roller in z-direction at (0, 1, 0), roller in y-direction at (0, 0, 1)
|
48
|
+
nod_00 = domain.get_nodenumber(0, 0, 0)
|
49
|
+
nod_10 = domain.get_nodenumber(0, 1, 0)
|
50
|
+
nod_01 = domain.get_nodenumber(0, 0, 1)
|
51
|
+
dofidx_left = np.concatenate([nodidx_left * 3, np.array([nod_00, nod_01]) * 3 + 1, np.array([nod_00, nod_10]) * 3 + 2])
|
52
|
+
nodidx_right = domain.get_nodenumber(*np.meshgrid(1, range(domain.nely + 1), range(domain.nelz + 1))).flatten()
|
53
|
+
|
54
|
+
E, nu = 210e+9, 0.3
|
55
|
+
|
56
|
+
s_x = pym.Signal('x', state=np.ones(domain.nel))
|
57
|
+
|
58
|
+
# Assemble stiffness matrix
|
59
|
+
m_K = pym.AssembleStiffness(s_x, domain=domain, bc=dofidx_left, e_modulus=E, poisson_ratio=nu)
|
60
|
+
s_K = m_K.sig_out[0]
|
61
|
+
|
62
|
+
m_K.response()
|
63
|
+
F = 1.5e+3
|
64
|
+
f = np.zeros(domain.nnodes * 3)
|
65
|
+
f[nodidx_right * 3] = F / nodidx_right.size
|
66
|
+
x = np.linalg.solve(s_K.state.toarray(), f)
|
67
|
+
|
68
|
+
# y and z displacements at (1, 0, 0) should be zero
|
69
|
+
npt.assert_allclose(x[domain.get_nodenumber(1, 0, 0) * 3 + 1], 0, atol=1e-10)
|
70
|
+
npt.assert_allclose(x[domain.get_nodenumber(1, 0, 0) * 3 + 2], 0, atol=1e-10)
|
71
|
+
|
72
|
+
# Z displacement at (1, 1, 0) should be zero
|
73
|
+
npt.assert_allclose(x[domain.get_nodenumber(1, 1, 0) * 3 + 2], 0, atol=1e-10)
|
74
|
+
|
75
|
+
# Y displacement at (1, 0, 1) should be zero
|
76
|
+
npt.assert_allclose(x[domain.get_nodenumber(1, 0, 1) * 3 + 1], 0, atol=1e-10)
|
77
|
+
|
78
|
+
# Analytical axial displacement using stiffness k = EA/L
|
79
|
+
ux_chk = F * Lx / (E * Ly * Lz)
|
80
|
+
npt.assert_allclose(x[nodidx_right * 3], ux_chk, rtol=1e-10)
|
81
|
+
|
82
|
+
# Transverse displacement using Poisson's effect
|
83
|
+
e_xx = ux_chk / Lx # Strain in x-direction
|
84
|
+
e_trans = - nu * e_xx
|
85
|
+
uy_chk = e_trans * Ly
|
86
|
+
npt.assert_allclose(x[domain.get_nodenumber(1, 1, 0) * 3 + 1], uy_chk, rtol=1e-10)
|
87
|
+
npt.assert_allclose(x[domain.get_nodenumber(1, 1, 1) * 3 + 1], uy_chk, rtol=1e-10)
|
88
|
+
|
89
|
+
uz_chk = e_trans * Lz
|
90
|
+
npt.assert_allclose(x[domain.get_nodenumber(1, 0, 1) * 3 + 2], uz_chk, rtol=1e-10)
|
91
|
+
npt.assert_allclose(x[domain.get_nodenumber(1, 1, 1) * 3 + 2], uz_chk, rtol=1e-10)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|