11# Required import for python
22import Sofa
33import SofaRuntime
4+ from Sofa import SofaLinearSystem
45from scipy import sparse
56from scipy import linalg
67from matplotlib import pyplot as plt
910exportCSV = False
1011showImage = 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
1326def 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