Skip to content

Commit

Permalink
Added material handling to .cnfg reader.
Browse files Browse the repository at this point in the history
It parses the material definitions into objects, then applies them to the
appropriate elements.  Currently only handles the four elements used in
existing Open Knee config files.
  • Loading branch information
randyheydon committed Nov 18, 2011
1 parent 5eb53e8 commit 41bf1ff
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 4 deletions.
50 changes: 47 additions & 3 deletions febabel/_formats/cnfg.py
Expand Up @@ -16,7 +16,7 @@
cp_kwargs = {}


from .. import problem
from .. import problem, materials as mat
from ._common import SETSEP, NSET, ESET

SEPCHAR = ','
Expand All @@ -28,6 +28,33 @@
INCL_KEY = '\nINCLUDE '


# Relates each material type name that can appear in a cnfg file to a function
# that takes the parameters dict and returns a material object.
# TODO: Density support for all materials.
# TODO: Cover more materials. Only these four are currently used in configs.
f = float
material_read_map = {
'rigid': lambda p: mat.Rigid(
map( f,p['com'].split(SEPCHAR) ), f(p['density']) ),
'Mooney-Rivlin': lambda p: mat.MooneyRivlin(
f(p['c1']), f(p['c2']), f(p['k']) ),
'Fung Orthotropic': lambda p: mat.FungOrthotropic(
f(p['e1']), f(p['e2']), f(p['e3']),
f(p['g12']), f(p['g23']), f(p['g31']),
f(p['v12']), f(p['v23']), f(p['v31']),
f(p['c']), f(p['k']), mat.NodalOrientation(
(int(p['axis1'])-1, int(p['axis2'])-1),
(int(p['axis1'])-1, int(p['axis3'])-1) ) ),
'trans iso Mooney-Rivlin': lambda p: mat.TransIsoElastic(
f(p['c3']), f(p['c4']), f(p['c5']),
f(p['lambda_star']), mat.NodalOrientation(
(int(p['fiber direction node 1'])-1, int(p['fiber direction node 2'])-1),
# Second edge is arbitrary for a trans iso material.
(int(p['fiber direction node 1'])-1, int(p['fiber direction node 2'])) ),
mat.MooneyRivlin( f(p['c1']), f(p['c2']), f(p['k']) ) ),
}



def _accrue_cnfg(filename, visited=frozenset()):
"Returns the text of the given file, with all INCLUDEs swapped in."
Expand Down Expand Up @@ -79,7 +106,7 @@ def read(self, filename):
# in the config file directly by set name. Otherwise, all sets must be
# accessed as "filename:setname".
# Note that str.startswith('') is always True.
geo_default = geo_files[0] if len(geo_files)==1 else ''
geo_default = '%s:'%geo_files[0] if len(geo_files)==1 else ''


# Collect all nodes in the geometry source files.
Expand Down Expand Up @@ -128,11 +155,28 @@ def read(self, filename):
node.x, node.y, node.z = pos


# Create materials and apply to sets.
for s in cp.sections():
if s.startswith(MATL_HEADER):
params = dict(cp.items(s))
mat = material_read_map[ params['type'] ](params)

# Get the set name to which the material is being applied.
# If the given set name already specifies its originating file, go
# with it. Otherwise (in a single-geometry config), add the geo
# file name to the set name.
eset = s[len(MATL_HEADER):]
if not eset.startswith(geo_default):
eset = geo_default + eset
for elem in self.sets[eset]:
elem.material = mat


# TODO: Something with solver settings.
# TODO: Generate materials, then apply to elements.
# TODO: Generate loadcurves.
# TODO: Generate constraints and their switches, then apply to bodies.
# TODO: Figure out contact.
# TODO: Generate springs.


problem.FEproblem.read_cnfg = read
91 changes: 90 additions & 1 deletion test/test_formats.py
Expand Up @@ -240,7 +240,96 @@ class TestCnfg(unittest.TestCase):
def test_read_cnfg(self):
p = f.problem.FEproblem()
p.read_cnfg(os.path.join(datadir, 'meniscectomy_kurosawa80.cnfg'))
# TODO: Some actual tests.

# Check tf_joint.inp's elements and nodes are present.
# NOTE: Nodes are moved from their original tf_joint.inp positions.
# This is checked visually. TODO: Proper transformation test.
self.assertEqual(len(p.sets['tf_joint.inp:allnodes']), 96853)
self.assertEqual(len(p.sets['tf_joint.inp:allelements']), 81653)

self.assertEqual(len(p.get_materials()), 15)

# Find each material in the elements of its corresponding set.
# Ensure all elements in the set have the same material, then test it.
for eset in ('femur', 'tibia'):
s = set(e.material for e in p.sets['tf_joint.inp:%s'%eset])
self.assertEqual(len(s), 1)
m = s.pop()
self.assertEqual(type(m), f.materials.Rigid)
self.assertEqual(m.density, 1.132e-6)
self.assertEqual(m.center_of_mass, [0,0,0])
for eset in ('fcartb', 'fcartm', 'fcartt', 'tcartb', 'tcartm', 'tcartt'):
s = set(e.material for e in p.sets['tf_joint.inp:%s'%eset])
self.assertEqual(len(s), 1)
m = s.pop()
self.assertEqual(type(m), f.materials.MooneyRivlin)
#self.assertEqual(m.density, 1.5e-9)
self.assertEqual(m.c1, 0.856)
self.assertEqual(m.c2, 0)
self.assertEqual(m.k, 8)
for eset in ('lat meni', 'med meni'):
s = set(e.material for e in p.sets['tf_joint.inp:%s'%eset])
self.assertEqual(len(s), 1)
m = s.pop()
self.assertEqual(type(m), f.materials.FungOrthotropic)
#self.assertEqual(m.density, 1.5e-9)
self.assertEqual(m.E1, 125)
self.assertEqual(m.E2, 27.5)
self.assertEqual(m.E3, 27.5)
self.assertEqual(m.v12, 0.1)
self.assertEqual(m.v23, 0.33)
self.assertEqual(m.v31, 0.1)
self.assertEqual(m.G12, 2)
self.assertEqual(m.G23, 12.5)
self.assertEqual(m.G31, 2)
self.assertEqual(m.c, 1)
self.assertEqual(m.k, 10)
self.assertEqual(m.axis_func.edge1, [6,7])
self.assertEqual(m.axis_func.edge2, [6,2])
for eset in ('acl', 'aclfiber'):
s = set(e.material for e in p.sets['tf_joint.inp:%s'%eset])
#self.assertEqual(len(s), 1) # FIXME: Why does this fail on acl?
m = s.pop()
self.assertEqual(type(m), f.materials.TransIsoElastic)
#self.assertEqual(m.density, 1.5e-9)
self.assertEqual(m.c3, 0.0139)
self.assertEqual(m.c4, 116.22)
self.assertEqual(m.c5, 535.039)
self.assertEqual(m.lam_max, 1.046)
self.assertEqual(m.axis_func.edge1, [0,3])
self.assertEqual(type(m.base), f.materials.MooneyRivlin)
self.assertEqual(m.base.c1, 1.95)
self.assertEqual(m.base.c2, 0)
self.assertEqual(m.base.k, 73.2)
s = set(e.material for e in p.sets['tf_joint.inp:pcl'])
self.assertEqual(len(s), 1)
m = s.pop()
self.assertEqual(type(m), f.materials.TransIsoElastic)
#self.assertEqual(m.density, 1.5e-9)
self.assertEqual(m.c3, 0.1196)
self.assertEqual(m.c4, 87.178)
self.assertEqual(m.c5, 431.063)
self.assertEqual(m.lam_max, 1.035)
self.assertEqual(m.axis_func.edge1, [0,3])
self.assertEqual(type(m.base), f.materials.MooneyRivlin)
self.assertEqual(m.base.c1, 3.25)
self.assertEqual(m.base.c2, 0)
self.assertEqual(m.base.k, 122)
for eset in ('mcl', 'lcl'):
s = set(e.material for e in p.sets['tf_joint.inp:%s'%eset])
self.assertEqual(len(s), 1)
m = s.pop()
self.assertEqual(type(m), f.materials.TransIsoElastic)
#self.assertEqual(m.density, 1.5e-9)
self.assertEqual(m.c3, 0.57)
self.assertEqual(m.c4, 48)
self.assertEqual(m.c5, 467.1)
self.assertEqual(m.lam_max, 1.063)
self.assertEqual(m.axis_func.edge1, [0,3])
self.assertEqual(type(m.base), f.materials.MooneyRivlin)
self.assertEqual(m.base.c1, 1.44)
self.assertEqual(m.base.c2, 0)
self.assertEqual(m.base.k, 397)



Expand Down

0 comments on commit 41bf1ff

Please sign in to comment.