forked from sofa-framework/SofaPython3
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathForceField.py
More file actions
150 lines (114 loc) · 5.7 KB
/
ForceField.py
File metadata and controls
150 lines (114 loc) · 5.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# coding: utf8
import unittest
import Sofa
import Sofa.Core
import Sofa.Helper
import Sofa.Simulation
import SofaRuntime
from MyRestShapeForceField import *
from numpy.linalg import norm as np_norm
def createIntegrationScheme(node, use_implicit_scheme):
if use_implicit_scheme is True:
node.addObject('EulerImplicitSolver', name='odeImplicitSolver',
rayleighStiffness='0.1', rayleighMass='0.1')
else:
node.addObject('EulerExplicitSolver', name='odeExplicitSolver')
def createSolver(node, use_iterative_solver):
if use_iterative_solver == True:
node.addObject('CGLinearSolver', name='linearSolver',
iterations=30, tolerance=1.e-9, threshold=1.e-9)
else:
node.addObject('EigenSimplicialLLT', name='ldlSolver')
def createParticle(node, node_name, use_implicit_scheme, use_iterative_solver):
p = node.addChild(node_name)
createIntegrationScheme(p, use_implicit_scheme)
createSolver(p, use_iterative_solver)
dofs = p.addObject('MechanicalObject', name="MO", position=[[0, 0, 0]])
p.addObject('UniformMass', totalMass=1.0)
myRSSFF = NaiveRestShapeSpringsForcefield(name="Springs",
stiffness=50,
mstate=dofs, rest_pos=dofs.rest_position)
p.addObject(myRSSFF)
def rssffScene(use_implicit_scheme=True, use_iterative_solver=True):
node = Sofa.Core.Node("root")
node.addObject('DefaultAnimationLoop')
node.addObject("RequiredPlugin", name="Sofa.Component.StateContainer")
node.addObject("RequiredPlugin", name="Sofa.Component.LinearSolver")
node.addObject("RequiredPlugin", name="Sofa.Component.ODESolver")
node.addObject("RequiredPlugin", name="Sofa.Component.Mass")
node.gravity = [0, -10, 0]
createParticle(node, "particle", use_implicit_scheme, use_iterative_solver)
return node
class EmptyForceField(Sofa.Core.ForceFieldVec3d):
def __init__(self, *args, **kwargs):
Sofa.Core.ForceFieldVec3d.__init__(self, *args, **kwargs)
pass
class Test(unittest.TestCase):
def test_class_name(self):
c = EmptyForceField()
self.assertEqual(c.getClassName(), "EmptyForceField")
def test_0_explicit(self):
root = rssffScene(use_implicit_scheme=False,
use_iterative_solver=False)
# do some steps here
Sofa.Simulation.init(root)
for i in range(0, 100):
Sofa.Simulation.animate(root, root.dt.value)
self.assertLess(np_norm(
root.particle.MO.rest_position.value - root.particle.MO.position.value), 0.41,
"Passed threshold on step " + str(i) + ".")
return
def test_1_implicit_iterative(self):
root = rssffScene(use_implicit_scheme=True, use_iterative_solver=True)
# do some steps here
Sofa.Simulation.init(root)
for i in range(0, 100):
Sofa.Simulation.animate(root, root.dt.value)
self.assertLess(np_norm(
root.particle.MO.rest_position.value - root.particle.MO.position.value), 0.26,
"Passed threshold on step " + str(i) + ".")
return
def test_2_implicit_direct(self):
root = rssffScene(use_implicit_scheme=True, use_iterative_solver=False)
# do some steps here
Sofa.Simulation.init(root)
for i in range(0, 100):
Sofa.Simulation.animate(root, root.dt.value)
self.assertLess(np_norm(
root.particle.MO.rest_position.value - root.particle.MO.position.value), 0.26,
"Passed threshold on step " + str(i) + ".")
return
@staticmethod
def simulate_beam(linear_solver_template):
root = Sofa.Core.Node("rootNode")
root.addObject('DefaultAnimationLoop')
root.addObject('RequiredPlugin', name='Sofa.Component.Topology.Container.Grid')
root.addObject('RequiredPlugin', name='Sofa.Component.ODESolver.Backward')
root.addObject('RequiredPlugin', name='Sofa.Component.LinearSolver.Direct')
root.addObject('RequiredPlugin', name='Sofa.Component.Engine.Select')
root.addObject('RequiredPlugin', name='Sofa.Component.Constraint.Projective')
root.addObject('RequiredPlugin', name='Sofa.Component.SolidMechanics.FEM.Elastic')
root.addObject('RequiredPlugin', name='Sofa.Component.Mass')
root.addObject('EulerImplicitSolver', rayleighStiffness="0.1", rayleighMass="0.1")
root.addObject('SparseLDLSolver', template=linear_solver_template)
root.addObject('MechanicalObject', name="DoFs")
root.addObject('UniformMass', name="mass", totalMass="320")
root.addObject('RegularGridTopology', name="grid", nx="4", ny="4", nz="20", xmin="-9", xmax="-6", ymin="0", ymax="3", zmin="0", zmax="19")
root.addObject('BoxROI', name="box", box=[-10, -1, -0.0001, -5, 4, 0.0001])
root.addObject('FixedConstraint', indices="@box.indices")
root.addObject('HexahedronFEMForceField', name="FEM", youngModulus="4000", poissonRatio="0.3", method="large")
Sofa.Simulation.init(root)
Sofa.Simulation.animate(root, 0.0001)
return root
def test_stiffness_matrix_access_scalar(self):
root = self.simulate_beam("CompressedRowSparseMatrixd")
K = root.FEM.assembleKMatrix()
self.assertEqual(K.ndim, 2)
self.assertEqual(K.shape, (960, 960))
self.assertEqual(K.nnz, 52200)
def test_stiffness_matrix_access_blocks3x3(self):
root = self.simulate_beam("CompressedRowSparseMatrixMat3x3d")
K = root.FEM.assembleKMatrix()
self.assertEqual(K.ndim, 2)
self.assertEqual(K.shape, (960, 960))
self.assertEqual(K.nnz, 52200)