Source code for woo.tests.shapepack

# encoding: utf-8
# 2013 © Václav Šmilauer <eu@doxos.eu>

from __future__ import print_function
import unittest
from minieigen import *
import woo._customConverters
import woo.core
import woo.dem
import woo.utils
import math
from woo.dem import *

[docs]class TestShapePack(unittest.TestCase): # def setUp(self):
[docs] def testLoadSampleTxt(self): 'ShapePack: load sample text file' data='''##PERIODIC:: 1. 1. 1. 0 Sphere 0 0 0 .1 1 Sphere .1 .1 .1 .1 1 Sphere .1 .1 .2 .1 2 Sphere .2 .2 .2 .2 2 Sphere .3 .3 .3 .3 2 Capsule .4 .4 .4 .3 .05 .05 .05 ''' tmp=woo.master.tmpFilename() f=open(tmp,'w'); f.write(data); f.close() sp=ShapePack(loadFrom=tmp) self.assertTrue(len(sp.raws)==3) self.assertTrue(type(sp.raws[1])==SphereClumpGeom) # automatic conversion for sphere-only clumps self.assertTrue(sp.raws[2].rawShapes[2].className=='Capsule') self.assertTrue(sp.cellSize[0]==1.)
# print sp.raws
[docs] def testSingle(self): 'ShapePack: single particles not clumped when inserted into simulation' S=woo.core.Scene(fields=[DemField()]) sp=ShapePack(raws=[SphereClumpGeom(centers=[(1,1,1)],radii=[.1]),RawShapeClump(rawShapes=[RawShape(className='Sphere',center=(2,2,2),radius=.2,raw=[])])]) mat=woo.utils.defaultMaterial() sp.toDem(S,S.dem,mat=mat) self.assertTrue(len(S.dem.nodes)==2) self.assertTrue(S.dem.par[0].pos==(1,1,1)) self.assertTrue(S.dem.par[1].shape.radius==.2) self.assertTrue(not S.dem.par[0].shape.nodes[0].dem.clumped) self.assertTrue(not S.dem.par[1].shape.nodes[0].dem.clumped)
[docs] def testFromSim(self): 'ShapePack: from/to simulation with particles' S=woo.core.Scene(fields=[DemField()]) # add two clumped spheres first r1,r2,p0,p1=1,.5,Vector3.Zero,Vector3(0,0,3) # adds clump node to S.dem.nodes automatically S.dem.par.addClumped([ woo.utils.sphere((0,0,0),1), woo.utils.sphere((0,0,3),.5) ]) # add a capsule c=woo.utils.capsule(center=(5,5,5),shaft=.3,radius=.3) S.dem.par.add(c,nodes=False) S.dem.nodesAppend(c.shape.nodes[0]) # from DEM sp=ShapePack() sp.fromDem(S,S.dem,mask=0) self.assertTrue(len(sp.raws)==2) self.assertTrue(type(sp.raws[0])==SphereClumpGeom) self.assertTrue(sp.raws[1].rawShapes[0].className=='Capsule') #print sp.raws # to DEM mat=woo.utils.defaultMaterial() S2=woo.core.Scene(fields=[DemField()]) sp.cellSize=(.2,.2,.2) sp.toDem(S2,S2.dem,mat=mat) # test that periodicity is used self.assertTrue(S2.periodic==True) self.assertTrue(S2.cell.size[0]==.2) # for p in S2.dem.par: print p, p.shape, p.shape.nodes[0] # for n in S2.dem.nodes: print n self.assertTrue(len(S2.dem.par)==3) # two spheres and capsule self.assertTrue(S2.dem.par[0].shape.nodes[0].dem.clumped) # sphere node is in clump self.assertTrue(S2.dem.par[0].shape.nodes[0] not in S2.dem.nodes) # sphere node not in dem.nodes self.assertTrue(S2.dem.nodes[0].dem.clump) # two-sphere clump node self.assertTrue(not S2.dem.nodes[1].dem.clump) # capsule node
# TODO: test that particle positions are as they should be
[docs] def assertAlmostEqualRel(self,a,b,relerr,abserr=0): self.assertAlmostEqual(a,b,delta=max(max(abs(a),abs(b))*relerr,abserr))
[docs] def testGridSamping(self): 'ShapePack: grid samping gives good approximations of mass+inertia' # take a single shape, compare with clump of zero-sized sphere (to force grid samping) and that shape m=woo.utils.defaultMaterial() zeroSphere=woo.utils.sphere((0,0,0),.4) # sphere which is entirely inside the thing for p in [woo.utils.sphere((0,0,0),1,mat=m),woo.utils.ellipsoid((0,0,0),semiAxes=(.8,1,1.2),mat=m),woo.utils.capsule((0,0,0),radius=.8,shaft=.6,mat=m)]: # print p.shape sp=woo.dem.ShapePack() sp.add([p.shape,zeroSphere.shape]) r=sp.raws[0] r.recompute(div=10) # this depends on how we define equivalent radius, which is not clear yet; so just skip it # self.assertAlmostEqualRel(r.equivRad,p.shape.equivRadius,1e-2) self.assertAlmostEqualRel(r.volume,p.mass/m.density,1e-2) # sorted since axes may be swapped ii1,ii2=sorted(r.inertia),sorted(p.inertia/m.density) for i1,i2 in zip(ii1,ii2): self.assertAlmostEqualRel(i1,i2,1e-2) for ax in (0,1,2): self.assertAlmostEqualRel(r.pos[ax],p.pos[ax],0,1e-2)
[docs] def testLineEndings(self): 'ShapePack: handle different line endings (LF, CR+LF, CR) gracefully' data='0 Sphere 0 0 0 .1|1 Sphere .1 .1 .1 .1|1 Sphere .1 .1 .2 .1|2 Sphere .2 .2 .2 .2|' for le,leName in [('\n','LF'),('\r\n','CR+LF'),('\r','CR')]: d2=data.replace('|',le) tmp=woo.master.tmpFilename() f=open(tmp,'w'); f.write(d2); f.close() try: sp=ShapePack(loadFrom=tmp) except: self.fail("Loading text file with line endings %s failed.") self.assertEqual(len(sp.raws),3)