Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions splib/Testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ def createScene(rootNode):
addImplicitODE(SimulatedLiver1)
addLinearSolver(SimulatedLiver1,iterative=False, template="CompressedRowSparseMatrixMat3x3")
loadMesh(SimulatedLiver1,filename="mesh/liver.msh")
addDynamicTopology(SimulatedLiver1,type=ElementType.TETRAHEDRONS,source="@meshLoader")
addDynamicTopology(SimulatedLiver1,type=ElementType.TETRAHEDRA,source="@meshLoader")
SimulatedLiver1.addObject("MechanicalObject",name="mstate", template='Vec3d')
SimulatedLiver1.addObject("LinearSolverConstraintCorrection",name="constraintCorrection")
addLinearElasticity(SimulatedLiver1,ElementType.TETRAHEDRONS, poissonRatio="0.3", youngModulus="3000", method='large')
addLinearElasticity(SimulatedLiver1,ElementType.TETRAHEDRA, poissonRatio="0.3", youngModulus="3000", method='large')
addMass(SimulatedLiver1,template='Vec3d',massDensity="2")
addFixation(SimulatedLiver1,ConstraintType.PROJECTIVE,boxROIs=[0, 3, 0, 2, 5, 2])

Expand Down
4 changes: 2 additions & 2 deletions splib/core/enum_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ class ElementType(Enum):
EDGES = 2
TRIANGLES = 3
QUADS = 4
TETRAHEDRONS = 5
HEXAHEDRONS = 6
TETRAHEDRA = 5
HEXAHEDRA = 6

class StateType(Enum):
VEC3 = 3
Expand Down
2 changes: 1 addition & 1 deletion splib/mechanics/hyperelasticity.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
@ReusableMethod
def addHyperelasticity(node,elem:ElementType,materialName=DEFAULT_VALUE, parameterSet=DEFAULT_VALUE, matrixRegularization=DEFAULT_VALUE,**kwargs):
match elem:
case ElementType.TETRAHEDRONS:
case ElementType.TETRAHEDRA:
node.addObject("TetrahedronHyperelasticityFEMForceField",name="constitutiveLaw", materialName=materialName, parameterSet=parameterSet, matrixRegularization=matrixRegularization, **kwargs)
return
case _:
Expand Down
18 changes: 9 additions & 9 deletions splib/mechanics/linear_elasticity.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,22 @@


@ReusableMethod
def addLinearElasticity(node,elem:ElementType,youngModulus=DEFAULT_VALUE, poissonRatio=DEFAULT_VALUE, method=DEFAULT_VALUE,**kwargs):
match elem:
def addLinearElasticity(node, elementType:ElementType, youngModulus=DEFAULT_VALUE, poissonRatio=DEFAULT_VALUE, method=DEFAULT_VALUE, **kwargs):
match elementType:
case ElementType.EDGES:
node.addObject("BeamFEMForceField",name="constitutiveLaw", youngModulus=youngModulus, poissonRatio=poissonRatio, method=method, **kwargs)
node.addObject("BeamFEMForceField", name="constitutiveLaw", youngModulus=youngModulus, poissonRatio=poissonRatio, method=method, **kwargs)
return
case ElementType.TRIANGLES:
node.addObject("TriangleFEMForceField",name="constitutiveLaw", youngModulus=youngModulus, poissonRatio=poissonRatio, method=method,**kwargs)
node.addObject("TriangleFEMForceField", name="constitutiveLaw", youngModulus=youngModulus, poissonRatio=poissonRatio, method=method, **kwargs)
return
case ElementType.QUADS:
node.addObject("QuadBendingFEMForceField",name="constitutiveLaw", youngModulus=youngModulus, poissonRatio=poissonRatio, method=method,**kwargs)
node.addObject("QuadBendingFEMForceField", name="constitutiveLaw", youngModulus=youngModulus, poissonRatio=poissonRatio, method=method, **kwargs)
return
case ElementType.TETRAHEDRONS:
node.addObject("TetrahedronFEMForceField",name="constitutiveLaw", youngModulus=youngModulus, poissonRatio=poissonRatio, method=method,**kwargs)
case ElementType.TETRAHEDRA:
node.addObject("TetrahedronFEMForceField", name="constitutiveLaw", youngModulus=youngModulus, poissonRatio=poissonRatio, method=method, **kwargs)
return
case ElementType.HEXAHEDRONS:
node.addObject("HexahedronFEMForceField",name="constitutiveLaw", youngModulus=youngModulus, poissonRatio=poissonRatio, method=method,**kwargs)
case ElementType.HEXAHEDRA:
node.addObject("HexahedronFEMForceField", name="constitutiveLaw", youngModulus=youngModulus, poissonRatio=poissonRatio, method=method, **kwargs)
return
case _:
print('Linear elasticity is only available for topology of type EDGES, TRIANGLES, QUADS, TETRAHEDRON, HEXAHEDRON')
Expand Down
10 changes: 5 additions & 5 deletions splib/mechanics/mass.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@

# TODO : use the massDensity only and deduce totalMass if necessary from it + volume
@ReusableMethod
def addMass(node,template,totalMass=DEFAULT_VALUE,massDensity=DEFAULT_VALUE,lumping=DEFAULT_VALUE,**kwargs):
def addMass(node, template, totalMass=DEFAULT_VALUE, massDensity=DEFAULT_VALUE, lumping=DEFAULT_VALUE, **kwargs):
if (not isDefault(totalMass)) and (not isDefault(massDensity)) :
print("[warning] You defined the totalMass and the massDensity in the same time, only taking massDensity into account")
kwargs.pop('massDensity')

if(template=="Rigid3"):
node.addObject("UniformMass",name="mass", totalMass=totalMass, massDensity=massDensity, lumping=lumping, **kwargs)
else:
node.addObject("MeshMatrixMass",name="mass", totalMass=totalMass, massDensity=massDensity, lumping=lumping, **kwargs)
# if(template=="Rigid3"):
node.addObject("UniformMass",name="mass", totalMass=totalMass, massDensity=massDensity, lumping=lumping, **kwargs)
# else:
# node.addObject("MeshMatrixMass",name="mass", totalMass=totalMass, massDensity=massDensity, lumping=lumping, **kwargs)



Expand Down
12 changes: 6 additions & 6 deletions splib/topology/dynamic.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,8 @@ def addHexahedronTopology(node,position=DEFAULT_VALUE,edges=DEFAULT_VALUE,quads=
node.addObject("HexahedronSetTopologyContainer", name="container", src=source, position=position, edges=edges, quads=quads, hexahedra=hexahedra, **kwargs)
# node.addObject("HexahedronSetGeometryAlgorithms", name="algorithms",**kwargs)

def addDynamicTopology(node,type:ElementType,**kwargs):

match type:
def addDynamicTopology(node, elementType:ElementType, **kwargs):
match elementType:
case ElementType.POINTS:
addPointTopology(node,**kwargs)
return
Expand All @@ -56,12 +55,13 @@ def addDynamicTopology(node,type:ElementType,**kwargs):
case ElementType.QUADS:
addQuadTopology(node,**kwargs)
return
case ElementType.TETRAHEDRONS:
case ElementType.TETRAHEDRA:
addTetrahedronTopology(node,**kwargs)
return
case ElementType.HEXAHEDRONS:
case ElementType.HEXAHEDRA:
addHexahedronTopology(node,**kwargs)
return
case _:
print('Topology type should be one of the following : "ElementType.POINTS, ElementType.EDGES, ElementType.TRIANGLES, ElementType.QUADS, ElementType.TETRAHEDRONS, ElementType.HEXAHEDRONS" ')
print('Topology type should be one of the following : "ElementType.POINTS, ElementType.EDGES, ElementType.TRIANGLES, ElementType.QUADS, ElementType.TETRAHEDRA, ElementType.HEXAHEDRA" ')
return

2 changes: 1 addition & 1 deletion splib/topology/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def loadMesh(node,filename,**kwargs):
elif splitedName[-1] == "sph":
return node.addObject("SphereLoader", name="loader",filename=filename, **kwargs)
else:
return node.addObject("Mesh"+splitedName[-1].upper()+"Loader", name="loader",filename=filename, **kwargs)
return node.addObject("Mesh"+splitedName[-1].upper()+"Loader", name="loader", filename=filename, **kwargs)
else:
print('[Error] : File extension ' + splitedName[-1] + ' not recognised.')

Expand Down
2 changes: 1 addition & 1 deletion splib/topology/static.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
from splib.core.utils import DEFAULT_VALUE

@ReusableMethod
def addStaticTopology(node,source=DEFAULT_VALUE,**kwargs):
def addStaticTopology(node, source=DEFAULT_VALUE, **kwargs):
node.addObject("MeshTopology", name="container", src=source, **kwargs)

10 changes: 5 additions & 5 deletions stlib/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
| -------------- | -------------------------------------------------------------- |
| Component* | Element of the scene hierarchy implementing a given behavior |
| ~~Object~~ | A deprecated synonym of a Component |
| Node* | Element of the scene hierarchy holding other Node (often refered as childs) or Objects |
| Node* | Element of the scene hierarchy holding other Nodes (often refered as childs) or Components |
| Data* | Attribute of a Component or a Node |
| Prefab | A Sofa.Node assembling of Objects and Nodes (a "fragment" of a scene) |
| Geometry | A prefab that describe shapes with their topologies (i.e a shape with its space descritization and its associated connectivity) |
| Entity | A physical prefab that represents real-world properties and behaviors used in a simulation. An entity should always have a geometry but includes neither a linear solver nor an integration scheme.|
| Parameters | Every prefab has a set of parameters. These parameters can contain data, links, callable or being composed of other parameters. Some of them can be optional. ~~Must inherit from `stlib.core.baseParameter.BaseParameter` and have a `@dataclasses.dataclass` decorator~~. Must have a `@stlib.parameters` decorator. |
| Prefab | A Node assembling of Components and Nodes (a "fragment" of a scene) |
| Geometry | A Prefab that describes shapes with their topologies (i.e a shapes with their space descritization and their associated connectivity) |
| Entity | A physical Prefab that represents real-world properties and behaviors used in a simulation. An entity should always have a geometry but includes neither a linear solver nor an integration scheme.|
| Parameters | Every Prefab has a set of parameters. These parameters can contain data, links, callable or being composed of other parameters. Some of them can be optional. ~~Must inherit from `stlib.core.baseParameter.BaseParameter` and have a `@dataclasses.dataclass` decorator~~. Must have a `@stlib.parameters` decorator. |

\*Defined in SOFA documentation [here](https://www.sofa-framework.org/doc/using-sofa/terminology).

Expand Down
2 changes: 1 addition & 1 deletion stlib/core/baseParameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

@dataclasses.dataclass
class BaseParameters(object):
name : str = "object"
name : str = "Object"
kwargs : dict = dataclasses.field(default_factory=dict)

def toDict(self):
Expand Down
45 changes: 24 additions & 21 deletions stlib/entities/__entity__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from stlib.core.baseParameters import BaseParameters
from stlib.core.basePrefab import BasePrefab
from stlib.prefabs.collision import CollisionParameters, Collision
from stlib.prefabs.visual import VisualParameters, Visual
from stlib.prefabs.material import Material, MaterialParameters
Expand All @@ -14,9 +15,9 @@

@dataclasses.dataclass
class EntityParameters(BaseParameters):
name = "Entity"
name : str = "Entity"

template : StateType = None
stateType : StateType = StateType.VEC3

### QUID
addCollision : Optional[Callable] = lambda x : Collision(CollisionParameters())
Expand All @@ -41,38 +42,40 @@ class Entity(BasePrefab):


def __init__(self, parameters=EntityParameters(), **kwargs):
Sofa.Core.Node.__init__(self, name=parameters.name)


BasePrefab.__init__(self, parameters)
self.parameters = parameters

self.geometry = self.add(Geometry, self.parameters.geometry)

### Check compatilibility of Material
if self.parameters.material.stateType != self.parameters.template:
if self.parameters.material.stateType != self.parameters.stateType:
print("WARNING: imcompatibility between templates of both the entity and the material")
self.parameters.material.stateType = self.parameters.template
self.parameters.material.stateType = self.parameters.stateType

self.material = self.add(Material,self.parameters.material)
self.material = self.add(Material, self.parameters.material)
self.material.States.position.parent = self.geometry.container.position.linkpath

if self.parameters.collision is not None:
self.collision = self.add(Collision,self.parameters.collision)
self.addMapping(self.parameters.collision, self.collision)

self.collision = self.add(Collision, self.parameters.collision)
self.addMapping(self.collision)

if self.parameters.visual is not None:
self.visual = self.add(Visual,self.parameters.visual)
self.addMapping(self.parameters.visual, self.visual)
self.visual = self.add(Visual, self.parameters.visual)
self.addMapping(self.visual)


def addMapping(self, destParameter, destPrefab):
def addMapping(self, destinationPrefab):

templateString = f'{self.parameters.template},{destParameter.template}'
template = f'{self.parameters.stateType},Vec3' # TODO: check that it is always true

if( self.parameters.template == StateType.VEC3):
if isinstance(destParameter.geometry,ExtractParameters):
destPrefab.addObject("IdentityMapping", input="@../material/", output="@.", template=templateString)
else :
destPrefab.addObject("BarycentricMapping", input="@../material/", output="@.", template=templateString)
if( self.parameters.stateType == StateType.VEC3):
destinationPrefab.addObject("BarycentricMapping",
input="@../Material/",
input_topology=destinationPrefab.geometry.container.linkpath,
output="@.",
template=template)
else:
destPrefab.addObject("RigidMapping", input="@../material", output="@.", template=templateString)
destinationPrefab.addObject("RigidMapping",
input="@../Material",
output="@.",
template=template)
85 changes: 30 additions & 55 deletions stlib/entities/deformable/__deformable__.py
Original file line number Diff line number Diff line change
@@ -1,71 +1,46 @@
from stlib.entities import Entity, EntityParameters
from stlib.prefabs.material import Material, MaterialParameters
from stlib.prefabs.visual import Visual
from splib.core.enum_types import ConstitutiveLaw, ElementType, StateType
from stlib.prefabs.material import MaterialParameters
from splib.core.enum_types import ConstitutiveLaw, ElementType
from stlib.core.baseParameters import Callable, Optional, dataclasses
from splib.mechanics.linear_elasticity import *
from splib.mechanics.hyperelasticity import *
from splib.mechanics.mass import addMass


@dataclasses.dataclass
class DeformableBehaviorParameters(MaterialParameters):

constitutiveLawType : ConstitutiveLaw = None
elementType : ElementType = None
parameters : list[float] = None

def addMaterial(self, node):

addMass(node, str(node.stateType), massDensity=node.massDensity, lumping=node.massLumping)
constitutiveLawType : ConstitutiveLaw = ConstitutiveLaw.ELASTIC
elementType : ElementType = ElementType.TETRAHEDRA
parameters : list[float] = dataclasses.field(default_factory=lambda: [1000, 0.45]) # young modulus, poisson ratio

def addDeformableMaterial(node):
addMass(node, node.parameters.stateType, massDensity=node.parameters.massDensity, lumping=node.parameters.massLumping)
# TODO : change this with inheritance
if(self.constitutiveLawType == ConstitutiveLaw.HYPERELASTIC):
addHyperelasticity(node,self.elementType, self.parameters)
if(node.parameters.constitutiveLawType == ConstitutiveLaw.HYPERELASTIC):
addHyperelasticity(node, node.parameters.elementType, node.parameters.parameters, topology="@../Geometry/container")
else:
addLinearElasticity(node,self.elementType, self.parameters[0], self.parameters[1])


# class Deformable(Entity):

# params : DeformableParameters

# @staticmethod
# def getParameters(**kwargs) -> DeformableParameters:
# return DeformableParameters(**kwargs)


# def __init__(self, params : DeformableParameters, **kwargs):
# Entity.__init__(self, **kwargs)

# self.__addConstitutiveLaw__()
# self.addCollision(params.collision)


# #@customizable
# # Need generic way of defining paramaters (linear/hyper...)
# def __addConstitutiveLaw__(self):
# self.params.addConstitutiveLaw()


# #@customizable
# def __addVisual__(self):
# #Extract surface and add identity mapping
# self.add(Visual, self.params.visual)


addLinearElasticity(node, node.parameters.elementType, node.parameters.parameters[0], node.parameters.parameters[1], topology="@../Geometry/container")

addMaterial : Optional[Callable] = addDeformableMaterial


def createScene(root) :

from stlib.entities import Entity, EntityParameters
from stlib.prefabs.visual import VisualParameters
from stlib.geometry.extract import ExtractParameters
from stlib.geometry.file import FileParameters
# from stlib.geometry.extract import ExtractParameters

liverParameters = EntityParameters()
liverParameters.template = StateType.VEC3
liverParameters.material = DeformableBehaviorParameters()
liverParameters.material.stateType = StateType.VEC3
liverParameters.material.constitutiveLawType = ConstitutiveLaw.ELASTIC
liverParameters.material.parameters = [1000, 0.45]
liverParameters.geometry = FileParameters("liver.vtk")
# liverParameters.visual = ExtractParameters()
myDeformableObject = root.add(Entity, liverParameters)
root.addObject("VisualStyle", displayFlags=["showBehavior"])

bunnyParameters = EntityParameters()
bunnyParameters.geometry = FileParameters(filename="mesh/Bunny.vtk")
bunnyParameters.geometry.elementType = ElementType.TETRAHEDRA # TODO: this is required by extract.py. Should it be done automatically in geometry.py ?
bunnyParameters.material = DeformableBehaviorParameters()
bunnyParameters.material.constitutiveLawType = ConstitutiveLaw.ELASTIC
bunnyParameters.material.parameters = [1000, 0.45]
bunnyParameters.visual = VisualParameters()
# bunnyParameters.visual.geometry = ExtractParameters(sourceParameters=bunnyParameters.geometry,
# destinationType=ElementType.TRIANGLES)
bunnyParameters.visual.geometry = FileParameters(filename="mesh/Bunny.stl")
bunnyParameters.visual.color = [1, 1, 1, 0.5]
bunny = root.add(Entity, bunnyParameters)
Loading
Loading