Skip to content

Commit b6dd289

Browse files
committed
add an example accessing the global system
1 parent b3fcd02 commit b6dd289

File tree

1 file changed

+64
-13
lines changed

1 file changed

+64
-13
lines changed

examples/access_mass_matrix.py

Lines changed: 64 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Required import for python
22
import Sofa
33
import SofaRuntime
4+
from Sofa import SofaLinearSystem
45
from scipy import sparse
56
from scipy import linalg
67
from matplotlib import pyplot as plt
@@ -9,6 +10,18 @@
910
exportCSV = False
1011
showImage = True
1112

13+
14+
def create_beam(node, id, offset):
15+
16+
node.addObject('MechanicalObject', name="DoFs")
17+
mass = node.addObject('MeshMatrixMass', name="mass" + str(id), totalMass=320)
18+
node.addObject('RegularGridTopology', name="grid", nx=4, ny=4, nz=20, xmin=-9 + offset, xmax=-6 + offset, ymin=0, ymax=3, zmin=0, zmax=19)
19+
node.addObject('BoxROI', name="box", box=[-10 + offset, -1, -0.0001, -5 + offset, 4, 0.0001])
20+
node.addObject('FixedProjectiveConstraint', indices="@box.indices")
21+
node.addObject('HexahedronFEMForceField', name="FEM", youngModulus=4000, poissonRatio=0.3, method="large")
22+
23+
node.addObject(LocalMatrixAccessController('MatrixAccessor', name='matrixAccessor', mass=mass))
24+
1225
# Function called when the scene graph is being created
1326
def createScene(root):
1427

@@ -17,6 +30,7 @@ def createScene(root):
1730
root.addObject("RequiredPlugin", pluginName=['Sofa.Component.Constraint.Projective',
1831
'Sofa.Component.Engine.Select',
1932
'Sofa.Component.LinearSolver.Direct',
33+
'Sofa.Component.LinearSystem',
2034
'Sofa.Component.Mass',
2135
'Sofa.Component.ODESolver.Backward',
2236
'Sofa.Component.SolidMechanics.FEM.Elastic',
@@ -29,22 +43,34 @@ def createScene(root):
2943
root.addObject('DefaultVisualManagerLoop')
3044

3145
root.addObject('EulerImplicitSolver', rayleighStiffness="0.1", rayleighMass="0.1")
32-
root.addObject('SparseLDLSolver', applyPermutation="false", template="CompressedRowSparseMatrixd")
3346

34-
root.addObject('MechanicalObject', name="DoFs")
35-
mass = root.addObject('MeshMatrixMass', name="mass", totalMass="320")
36-
root.addObject('RegularGridTopology', name="grid", nx="4", ny="4", nz="20", xmin="-9", xmax="-6", ymin="0", ymax="3", zmin="0", zmax="19")
37-
root.addObject('BoxROI', name="box", box="-10 -1 -0.0001 -5 4 0.0001")
38-
root.addObject('FixedConstraint', indices="@box.indices")
39-
root.addObject('HexahedronFEMForceField', name="FEM", youngModulus="4000", poissonRatio="0.3", method="large")
40-
41-
root.addObject(MatrixAccessController('MatrixAccessor', name='matrixAccessor', mass=mass))
47+
matrices = root.addChild('matrices')
48+
# in this Node, two linear systems are declared:
49+
# 1) one used to assemble the global system used by the solver, and
50+
# 2) another assembling only the mass contributions
51+
matrices.addObject('MatrixLinearSystem', template="CompressedRowSparseMatrixMat3x3d", name='system')
52+
mass_matrix = matrices.addObject('MatrixLinearSystem', template="CompressedRowSparseMatrixMat3x3d", name='M',
53+
assembleStiffness=False, assembleDamping=False, assembleGeometricStiffness=False,
54+
applyProjectiveConstraints=False) # This system assembles only the mass contributions
55+
matrices.addObject(GlobalMatrixAccessController('MatrixAccessor', name='matrixAccessor', mass_matrix=mass_matrix))
56+
57+
# This component distributes the matrix contributions to the other systems
58+
root.addObject('CompositeLinearSystem', template="CompressedRowSparseMatrixMat3x3d", name="solverSystem",
59+
linearSystems="@matrices/system @matrices/M", solverLinearSystem="@matrices/system")
60+
# It is important to define the linear system in the linear solver: the CompositeLinearSystem
61+
root.addObject('SparseLDLSolver', ordering='Natural', template="CompressedRowSparseMatrixMat3x3d",
62+
linearSystem="@solverSystem")
63+
64+
beam1 = root.addChild('Beam1')
65+
create_beam(beam1, 1, 0)
66+
67+
beam2 = root.addChild('Beam2')
68+
create_beam(beam2, 2, 10)
4269

4370
return root
4471

4572

46-
class MatrixAccessController(Sofa.Core.Controller):
47-
73+
class LocalMatrixAccessController(Sofa.Core.Controller):
4874

4975
def __init__(self, *args, **kwargs):
5076
Sofa.Core.Controller.__init__(self, *args, **kwargs)
@@ -54,7 +80,32 @@ def onAnimateEndEvent(self, event):
5480
mass_matrix = self.mass.assembleMMatrix()
5581

5682
print('====================================')
57-
print('Stiffness matrix')
83+
print('Mass matrix', self.mass.getPathName())
84+
print('====================================')
85+
print('dtype: ' + str(mass_matrix.dtype))
86+
print('shape: ' + str(mass_matrix.shape))
87+
print('ndim: ' + str(mass_matrix.ndim))
88+
print('nnz: ' + str(mass_matrix.nnz))
89+
print('norm: ' + str(sparse.linalg.norm(mass_matrix)))
90+
91+
if exportCSV:
92+
np.savetxt(self.mass.getName() + '.csv', mass_matrix.toarray(), delimiter=',')
93+
if showImage:
94+
plt.imshow(mass_matrix.toarray(), interpolation='nearest', cmap='gist_gray')
95+
plt.show(block=False)
96+
97+
98+
class GlobalMatrixAccessController(Sofa.Core.Controller):
99+
100+
def __init__(self, *args, **kwargs):
101+
Sofa.Core.Controller.__init__(self, *args, **kwargs)
102+
self.mass_system = kwargs.get("mass_matrix")
103+
104+
def onAnimateEndEvent(self, event):
105+
mass_matrix = self.mass_system.A()
106+
107+
print('====================================')
108+
print('Mass matrix', self.mass_system.getPathName())
58109
print('====================================')
59110
print('dtype: ' + str(mass_matrix.dtype))
60111
print('shape: ' + str(mass_matrix.shape))
@@ -63,7 +114,7 @@ def onAnimateEndEvent(self, event):
63114
print('norm: ' + str(sparse.linalg.norm(mass_matrix)))
64115

65116
if exportCSV:
66-
np.savetxt('mass.csv', mass_matrix.toarray(), delimiter=',')
117+
np.savetxt(self.mass_system.getName() + '.csv', mass_matrix.toarray(), delimiter=',')
67118
if showImage:
68119
plt.imshow(mass_matrix.toarray(), interpolation='nearest', cmap='gist_gray')
69120
plt.show(block=False)

0 commit comments

Comments
 (0)