def testDiagonalEigenVectors(self): for i in xrange(self.ntests): lam1 = rangen.uniform(-ranrange, ranrange) lam2 = rangen.uniform(-ranrange, ranrange) lam3 = rangen.uniform(-ranrange, ranrange) A = SymTensor3d(lam1, 0.0, 0.0, 0.0, lam2, 0.0, 0.0, 0.0, lam3) A = SymTensor3d(lam1, 0.0, 0.0, 0.0, lam2, 0.0, 0.0, 0.0, lam3) lam0 = [(lam1, Vector3d(1, 0, 0)), (lam2, Vector3d(0, 1, 0)), (lam3, Vector3d(0, 0, 1))] lam0.sort() eigenVecs0 = [x[1] for x in lam0] eigenStruct = A.eigenVectors() lam = [(eigenStruct.eigenValues(i), eigenStruct.eigenVectors.getColumn(i)) for i in range(3)] lam.sort() eigenVecs = [x[1] for x in lam] for (x, x0) in zip(eigenVecs, eigenVecs0): self.failUnless( fuzzyEqual(x.magnitude(), 1.0), "Eigen vector %s does not equal expected value %s" % (str(x), str(x0))) self.failUnless( fuzzyEqual(abs(x.dot(x0)), 1.0), "Eigen vector %s does not equal expected value %s" % (str(x), str(x0))) return
def testWsumValues3d(self): W = self.WT3 assert len(W.nperh()) == len(W.Wsum()) for nperh, Wsum in zip(W.nperh(), W.Wsum()): deta = 1.0 / nperh nx = int(W.kernelExtent() * nperh) + 1 testSum = 0.0 for iz in xrange(nx): etaz = iz * deta for iy in xrange(nx): etay = iy * deta for ix in xrange(nx): etax = ix * deta eta = sqrt(etax * etax + etay * etay + etaz * etaz) delta = W.kernelValue(eta, 1.0) if ix > 0: delta *= 2.0 if iy > 0: delta *= 2.0 if iz > 0: delta *= 2.0 testSum += delta self.failUnless(fuzzyEqual(Wsum, testSum, self.Wsumtol), "Wsum failure: %g != %g: " % (Wsum, testSum)) self.failUnless( fuzzyEqual(W.equivalentNodesPerSmoothingScale(testSum), nperh, self.Wsumtol), "Lookup n per h failure: %g %g %g" % (testSum, W.equivalentNodesPerSmoothingScale(testSum), nperh)) return
def testRotation(self): R = randomRotationMatrix(self.TensorType.nDimensions) assert fuzzyEqual(R.Determinant(), 1.0) check = R*self.lhs*R.Transpose() self.lhs.rotationalTransform(R) for row in xrange(self.TensorType.nDimensions): for col in xrange(self.TensorType.nDimensions): assert fuzzyEqual(self.lhs(row, col), check(row, col)) return
def testDotUnitFull(self): one = self.FullTensorType.one resultr = one * self.rhs resultl = self.lhs * one for row in xrange(self.TensorType.nDimensions): for col in xrange(self.TensorType.nDimensions): assert fuzzyEqual(resultl(row, col), self.lhs(row, col)) assert fuzzyEqual(resultr(row, col), self.rhs(row, col)) return
def testInverse(self): result = self.lhs.Inverse() check = result*self.lhs for row in xrange(self.TensorType.nDimensions): for col in xrange(self.TensorType.nDimensions): if row == col: assert fuzzyEqual(check(row, col), 1.0) else: self.failUnless(fuzzyEqual(check(row, col), 0.0, 1.0e-5), "Off diagonal not zero: %s" % str(check)) return
def testDoublyDegenerateEigenVectors(self): for i in xrange(self.ntests): lam12 = rangen.uniform(-ranrange, ranrange) A, vlam0, vectors0 = randomSymTensor3d(lam1=lam12, lam2=lam12) lam0 = [(vlam0(i), vectors0.getColumn(i)) for i in range(3)] lam0.sort() eigenVecs0 = [x[1] for x in lam0] eigenStruct = A.eigenVectors() lam = [(eigenStruct.eigenValues(i), eigenStruct.eigenVectors.getColumn(i)) for i in range(3)] lam.sort() eigenVecs = [x[1] for x in lam] for x in eigenVecs: self.failUnless( fuzzyEqual(x.magnitude(), 1.0), "Eigen vector %s does not have unit magnitude %s" % (str(x), str(eigenStruct.eigenVectors))) # Identify the unique eigen value. unique = -1 thpt = 0.0 degenerate = [] if (lam0[0][0] == lam0[1][0]): unique = 2 degenerate = [0, 1] thpt = abs(vlam0(2)) / (abs(vlam0(0)) + 1.0e-10) else: unique = 0 degenerate = [1, 2] thpt = abs(vlam0(0)) / (abs(vlam0(1)) + 1.0e-10) assert thpt > 0.0 if thpt > 1.0: thpt = 1.0 / thpt # Does the eigenvector for the unique eigen value match? self.failUnless( fuzzyEqual(abs(eigenVecs[unique].dot(eigenVecs0[unique])), 1.0, degenerateFuzz(unique, [x[0] for x in lam0])), "Eigen vector %s does not equal expected value %s for eigen values %s, %s" % (str(eigenVecs[unique]), str(eigenVecs0[unique]), str(vlam0), str(eigenStruct.eigenValues))) # The remaining eigen values need only be perpendicular to each other and the unique # value. self.failUnless( fuzzyEqual(eigenVecs[0].dot(eigenVecs[1]), 0.0) and fuzzyEqual(eigenVecs[0].dot(eigenVecs[2]), 0.0) and fuzzyEqual(eigenVecs[1].dot(eigenVecs[2]), 0.0), "Eigen vectors (%s, %s, %s) are not orthogonal\n%s" % (str(eigenVecs[0]), str(eigenVecs[1]), str( eigenVecs[2]), str(eigenStruct.eigenValues))) return
def testScalarDivision(self): val = 44.0 result = self.lhs / val assert isinstance(result, self.VectorType) for i in xrange(self.VectorType.nDimensions): assert fuzzyEqual(result(i), self.lhs(i) / val) return
def testSelfDoubleDot(self): result = self.lhs.selfDoubledot() check = self.lhs.doubledot(self.lhs) self.failUnless( fuzzyEqual(result, check), "selfDoubledot check failure: %f != %f" % (result, check)) return
def testSquare(self): result = self.lhs.square() check = self.lhs * self.lhs for row in xrange(self.TensorType.nDimensions): for col in xrange(self.TensorType.nDimensions): self.failUnless(fuzzyEqual(result(row, col), check(row, col)), "Bad value: (%i,%i), %g != %g" % (row, col, result(row, col), check(row, col)))
def testCuberoot(self): tol = {1: 1e-5, 2: 1e-5, 3: 5e-4}[self.TensorType.nDimensions] for t in xrange(nrandom): st = randomSymmetricMatrix(self.TensorType.nDimensions) st13 = st.cuberoot() st13cube = st13*st13*st13 diff = st13cube - st check = diff.doubledot(diff) self.failUnless(fuzzyEqual(check, 0.0, tol), "CUBEROOT failure %s != %s, eigen values=%s, check=%g" % (str(st13cube), str(st), str(st.eigenValues()), check)) return ## def testPow(self): ## tol = {1: 1e-5, ## 2: 1e-5, ## 3: 1e-3}[self.TensorType.nDimensions] ## for t in xrange(nrandom): ## st = randomSymmetricMatrix(self.TensorType.nDimensions) ## p = abs(rangen.choice([rangen.uniform(-5.0, -0.5), rangen.uniform(0.5, 5.0)])) ## stp = st.pow(p) ## stpi = stp.pow(1.0/p) ## diff = stpi - st ## check = diff.doubledot(diff) ## self.failUnless(fuzzyEqual(check, 0.0, tol), ## "POW failure %s !=\n %s,\n power = %f,\n eigen values=%s\n %s,\n check=%g" % (str(stpi), str(st), p, ## str(stpi.eigenValues()), ## str(st.eigenValues()), ## check)) return
def testClosestPointOnFacets(self): facets = self.polygon.facets for f in facets: p = f.position cp = self.polygon.closestPoint(p) self.failUnless(fuzzyEqual((cp - p).magnitude(), 0.0, 1.0e-10), "Closest point to facet position %s : %s" % (p, cp))
def testMagnitude(self): result = self.lhs.magnitude() check = 0.0 for i in xrange(self.VectorType.nDimensions): check += (self.lhs(i))**2 check = sqrt(check) assert fuzzyEqual(result, check)
def testSquareElements(self): result = self.lhs.squareElements() for row in xrange(self.TensorType.nDimensions): for col in xrange(self.TensorType.nDimensions): self.failUnless(fuzzyEqual(result(row, col), self.lhs(row, col)**2), "Square matrix elements failure: %g != %g" % (result(row, col), self.lhs(row, col)**2)) return
def testTriplyDegenerateEigenVectors(self): for i in xrange(self.ntests): lam123 = rangen.uniform(-ranrange, ranrange) A = SymTensor3d(lam123, 0.0, 0.0, 0.0, lam123, 0.0, 0.0, 0.0, lam123) vlam0 = Vector3d(lam123, lam123, lam123) vectors0 = [ Vector3d(1, 0, 0), Vector3d(0, 1, 0), Vector3d(0, 0, 1) ] eigenStruct = A.eigenVectors() for i in xrange(3): vec = eigenStruct.eigenVectors.getColumn(i) match = [ fuzzyEqual(abs(vec.dot(vectors0[j])), 1.0) for j in xrange(len(vectors0)) ] assert len(match) == len(vectors0) assert sum(match) == 1 del vectors0[match.index(True)] self.failUnless( len(vectors0) == 0, "Failed triply degenerate eigen vector decomposition: %s %s." % (str(eigenStruct.eigenVectors), str(lam123))) return
def testScalarDivision(self): val = 44.0 result = self.lhs / val assert isinstance(result, self.TensorType) for row in xrange(self.TensorType.nDimensions): for col in xrange(self.TensorType.nDimensions): assert fuzzyEqual(result(row, col), self.lhs(row, col) / val) return
def testClipInternalTwoPlanes(self): for points, neighbors, facets in self.polyData: poly = Polyhedron(points, facets) PCpoly = PolyClipper.Polyhedron() PolyClipper.convertToPolyhedron(PCpoly, poly) for i in xrange(self.ntests): p0 = Vector(rangen.uniform(0.0, 1.0), rangen.uniform(0.0, 1.0), rangen.uniform(0.0, 1.0)) norm1 = Vector(rangen.uniform(-1.0, 1.0), rangen.uniform(-1.0, 1.0), rangen.uniform(-1.0, 1.0)).unitVector() norm2 = Vector(rangen.uniform(-1.0, 1.0), rangen.uniform(-1.0, 1.0), rangen.uniform(-1.0, 1.0)).unitVector() planes1 = vector_of_PolyClipperPlane() planes1.append(PolyClipper.PolyClipperPlane3d(p0, norm1)) planes1.append(PolyClipper.PolyClipperPlane3d(p0, norm2)) planes2 = vector_of_PolyClipperPlane() planes2.append(PolyClipper.PolyClipperPlane3d(p0, norm1)) planes2.append(PolyClipper.PolyClipperPlane3d(p0, -norm2)) planes3 = vector_of_PolyClipperPlane() planes3.append(PolyClipper.PolyClipperPlane3d(p0, -norm1)) planes3.append(PolyClipper.PolyClipperPlane3d(p0, norm2)) planes4 = vector_of_PolyClipperPlane() planes4.append(PolyClipper.PolyClipperPlane3d(p0, -norm1)) planes4.append(PolyClipper.PolyClipperPlane3d(p0, -norm2)) PCchunk1 = PolyClipper.Polyhedron(PCpoly) PCchunk2 = PolyClipper.Polyhedron(PCpoly) PCchunk3 = PolyClipper.Polyhedron(PCpoly) PCchunk4 = PolyClipper.Polyhedron(PCpoly) PolyClipper.clipPolyhedron(PCchunk1, planes1) PolyClipper.clipPolyhedron(PCchunk2, planes2) PolyClipper.clipPolyhedron(PCchunk3, planes3) PolyClipper.clipPolyhedron(PCchunk4, planes4) chunk1 = Polyhedron(poly) chunk2 = Polyhedron(poly) chunk3 = Polyhedron(poly) chunk4 = Polyhedron(poly) PolyClipper.convertFromPolyhedron(chunk1, PCchunk1) PolyClipper.convertFromPolyhedron(chunk2, PCchunk2) PolyClipper.convertFromPolyhedron(chunk3, PCchunk3) PolyClipper.convertFromPolyhedron(chunk4, PCchunk4) success = fuzzyEqual( chunk1.volume + chunk2.volume + chunk3.volume + chunk4.volume, poly.volume) if not success: writePolyhedronOBJ(poly, "poly.obj") writePolyhedronOBJ(chunk1, "chunk_1ONE_TWOPLANES.obj") writePolyhedronOBJ(chunk2, "chunk_2TWO_TWOPLANES.obj") writePolyhedronOBJ(chunk3, "chunk_3THREE_TWOPLANES.obj") writePolyhedronOBJ(chunk4, "chunk_4FOUR_TWOPLANES.obj") self.failUnless( success, "Two plane clipping summing to wrong volumes: %s + %s + %s + %s = %s != %s" % (chunk1.volume, chunk2.volume, chunk3.volume, chunk4.volume, chunk1.volume + chunk2.volume + chunk3.volume + chunk4.volume, poly.volume)) return
def randomSymTensor3d(lam1=None, lam2=None, lam3=None): if lam1 is None: lam1 = rangen.uniform(-ranrange, ranrange) if lam2 is None: lam2 = rangen.uniform(-ranrange, ranrange) if lam3 is None: lam3 = rangen.uniform(-ranrange, ranrange) # Pick random Euler angles. theta = rangen.uniform(0.0, 2.0 * pi) phi = rangen.uniform(0.0, pi) psi = rangen.uniform(0.0, pi) # Build the rotation matrix of eigen vectors. R = Tensor3d( cos(psi) * cos(phi) - cos(theta) * sin(phi) * sin(psi), -sin(psi) * cos(phi) - cos(theta) * sin(phi) * cos(psi), sin(theta) * sin(phi), cos(psi) * sin(phi) + cos(theta) * cos(phi) * sin(psi), -sin(psi) * sin(phi) + cos(theta) * cos(phi) * cos(psi), -sin(theta) * cos(phi), sin(theta) * sin(psi), sin(theta) * cos(psi), cos(theta)) assert fuzzyEqual(R.Determinant(), 1.0) check = R * R.Transpose() for i in xrange(3): for j in xrange(3): if i == j: assert fuzzyEqual(check(i, j), 1.0) else: assert fuzzyEqual(check(i, j), 0.0) # Check the eigen vectors. vec1 = R.getColumn(0) vec2 = R.getColumn(1) vec3 = R.getColumn(2) assert fuzzyEqual(vec1.magnitude(), 1.0) assert fuzzyEqual(vec2.magnitude(), 1.0) assert fuzzyEqual(vec3.magnitude(), 1.0) assert fuzzyEqual(vec1.dot(vec2), 0.0) assert fuzzyEqual(vec3.dot(vec1), 0.0) assert fuzzyEqual(vec3.dot(vec2), 0.0) # Now put it all together into our final symmetric matrix. A = SymTensor3d(lam1, 0.0, 0.0, 0.0, lam2, 0.0, 0.0, 0.0, lam3) A.rotationalTransform(R) # Return the tensor, it's eigen values, and the tensor of eigenvectors. return A, Vector3d(lam1, lam2, lam3), R
def testDoubleDot(self): result = self.lhs.doubledot(self.rhs) check = 0 for row in xrange(self.TensorType.nDimensions): for col in xrange(self.TensorType.nDimensions): check += self.lhs(row, col)*self.rhs(col, row) self.failUnless(fuzzyEqual(result, check), "Doubledot check failure: %f != %f" % (result, check)) return
def testClosestPointAboveFacets(self): facets = self.polygon.facets for f in facets: chi = rangen.uniform(0.1, 10.0) cp0 = f.position p = cp0 + chi*f.normal cp = self.polygon.closestPoint(p) self.failUnless(fuzzyEqual((cp0 - cp).magnitude(), 0.0, 1.0e-10), "Closest point to position off of facet position %s : %s" % (cp0, cp))
def testVolume(self): facets = self.polyhedron.facets() c = self.polyhedron.centroid() answer = 0.0 for f in facets: answer += f.area * (f.normal.dot(f.point(0) - c)) answer /= 3.0 self.failUnless(fuzzyEqual(self.polyhedron.volume, answer, 1.0e-10), "Failed volume computation: %g != %g" % (self.polyhedron.volume, answer))
def testCube(self): for t in xrange(nrandom): st = randomSymmetricMatrix(self.TensorType.nDimensions) st3 = st.cube() check = st*st*st for row in xrange(self.TensorType.nDimensions): for col in xrange(self.TensorType.nDimensions): self.failUnless(fuzzyEqual(st3(row, col), check(row, col)), "CUBE failure %s != %s" % (str(st3), str(check))) return
def testIntersectTouchingBox(self): xmin = self.polygon.xmin.x vertex = None for v in self.polygon.vertices: if fuzzyEqual(v.x, xmin, 1.0e-10): vertex = v assert not vertex is None box = (Vector(v.x - 2.0, v.y - 2.0), v) self.failUnless(self.polygon.intersect(box), "Failed to intersect with a box touching on one side.")
def testOtherTensorMultiplication(self): result = self.lhs * self.other assert isinstance(result, self.FullTensorType) for row in xrange(self.TensorType.nDimensions): for col in xrange(self.TensorType.nDimensions): check = 0.0 for i in xrange(self.TensorType.nDimensions): check += self.lhs(row, i) * self.other(i, col) assert fuzzyEqual(result(row, col), check) return
def testInPlaceScalarDivision(self): val = 44.0 result = self.TensorType(self.lhs) result /= val assert isinstance(result, self.TensorType) for row in xrange(self.TensorType.nDimensions): for col in xrange(self.TensorType.nDimensions): self.failUnless(fuzzyEqual(result(row, col), self.lhs(row, col) / val), "Tensor inplace division : %g != %g" % (result(row, col), self.lhs(row, col) / val)) return
def testWlookup(self): for W, WT in self.kernelPairs: deta = W.kernelExtent() / (self.nsamples - 1) for i in xrange(self.nsamples): eta = i * deta self.failUnless( fuzzyEqual(WT.kernelValue(eta, 1.0), W.kernelValue(eta, 1.0), self.W0tol), "TableKernel value does match original within tolerance: %g %g" % (WT.kernelValue(eta, 1.0), W.kernelValue(eta, 1.0))) self.failUnless( fuzzyEqual(WT.gradValue(eta, 1.0), W.gradValue(eta, 1.0), self.W1tol), "TableKernel grad value does match original within tolerance: %g %g" % (WT.gradValue(eta, 1.0), W.gradValue(eta, 1.0))) self.failUnless( fuzzyEqual(WT.grad2Value(eta, 1.0), W.grad2Value(eta, 1.0), self.W2tol), "TableKernel grad2 value does match original within tolerance: %g %g" % (WT.grad2Value(eta, 1.0), W.grad2Value(eta, 1.0)))
def testSqrt(self): tol = {1: 1e-5, 2: 1e-5, 3: 1e-3}[self.TensorType.nDimensions] for t in xrange(nrandom): st = randomPositiveSymmetricMatrix(self.TensorType.nDimensions) st12 = st.sqrt() st12squared = st12 * st12 diff = st12squared - st check = diff.doubledot(diff) self.failUnless( fuzzyEqual(check, 0.0, tol), "SQRT failure %s != %s, eigen values=%s, %g" % (str(st12squared), str(st), str(st.eigenValues()), check)) return
def testRandomEigenValues(self): for i in xrange(self.ntests): A, vlam0, vectors0 = randomSymTensor3d() lam0 = [x for x in vlam0] lam0.sort() vlam = A.eigenValues() lam = [x for x in vlam] lam.sort() for (x, x0) in zip(lam, lam0): self.failUnless( fuzzyEqual(x, x0, 1e-5), "Eigen values %s do not equal expected values %s" % (str(lam), str(lam0))) return
def testClipInternalTwoPlanes(self): for points in self.pointSets: PCpoly = PolyClipperPolygon() initializePolygon(PCpoly, points, vertexNeighbors(points)) poly = Polygon(points, facets(points)) for i in xrange(self.ntests): p0 = Vector(rangen.uniform(0.0, 1.0), rangen.uniform(0.0, 1.0)) norm1 = Vector(rangen.uniform(-1.0, 1.0), rangen.uniform(-1.0, 1.0)).unitVector() norm2 = Vector(rangen.uniform(-1.0, 1.0), rangen.uniform(-1.0, 1.0)).unitVector() planes1 = [] planes1.append(PolyClipperPlane2d(p0, norm1)) planes1.append(PolyClipperPlane2d(p0, norm2)) planes2 = [] planes2.append(PolyClipperPlane2d(p0, norm1)) planes2.append(PolyClipperPlane2d(p0, -norm2)) planes3 = [] planes3.append(PolyClipperPlane2d(p0, -norm1)) planes3.append(PolyClipperPlane2d(p0, norm2)) planes4 = [] planes4.append(PolyClipperPlane2d(p0, -norm1)) planes4.append(PolyClipperPlane2d(p0, -norm2)) PCchunk1 = PolyClipperPolygon(PCpoly) PCchunk2 = PolyClipperPolygon(PCpoly) PCchunk3 = PolyClipperPolygon(PCpoly) PCchunk4 = PolyClipperPolygon(PCpoly) clipPolygon(PCchunk1, planes1) clipPolygon(PCchunk2, planes2) clipPolygon(PCchunk3, planes3) clipPolygon(PCchunk4, planes4) chunk1, clips = convertFromPolyClipper(PCchunk1) chunk2, clips = convertFromPolyClipper(PCchunk2) chunk3, clips = convertFromPolyClipper(PCchunk3) chunk4, clips = convertFromPolyClipper(PCchunk4) success = fuzzyEqual( chunk1.volume + chunk2.volume + chunk3.volume + chunk4.volume, poly.volume) if not success: writePolyhedronOBJ(poly, "poly.obj") writePolyhedronOBJ(chunk1, "chunk_1ONE_TWOPLANES.obj") writePolyhedronOBJ(chunk2, "chunk_2TWO_TWOPLANES.obj") writePolyhedronOBJ(chunk3, "chunk_3THREE_TWOPLANES.obj") writePolyhedronOBJ(chunk4, "chunk_4FOUR_TWOPLANES.obj") self.failUnless( success, "Two plane clipping summing to wrong volumes: %s + %s + %s + %s = %s != %s" % (chunk1.volume, chunk2.volume, chunk3.volume, chunk4.volume, chunk1.volume + chunk2.volume + chunk3.volume + chunk4.volume, poly.volume))
def testVolume(self): verts0 = self.polygon.vertices c = self.polygon.centroid cmpmethod = SortCounterClockwise(c) verts = sorted(list(verts0), cmpmethod) p0 = verts[0] answer = 0.0 for i in xrange(2, len(verts)): answer += (verts[i] - p0).cross(verts[i - 1] - p0).z answer *= 0.5 vertstring = [str(x) for x in verts] self.failUnless(fuzzyEqual(self.polygon.volume, answer, 1.0e-10), "Failed volume computation: %g != %g\n verts = %s" % (self.polygon.volume, answer, vertstring))
def testBoundingSurface(self): mesh, void = generateLineMesh([self.nodes], xmin=xmin, xmax=xmax, generateParallelConnectivity=True) bs = mesh.boundingSurface() assert fuzzyEqual(bs.xmin.x, x0, 1.0e-10) assert fuzzyEqual(bs.xmax.x, x1, 1.0e-10) # Check that all the generators are contained. pos = self.nodes.positions() for i in xrange(self.nodes.numInternalNodes): self.failUnless( bs.contains(pos[i]), "Failed containment for generator %i @ %s" % (i, pos[i])) # Check that all mesh nodes are contained. for i in xrange(mesh.numNodes): self.failUnless( bs.contains(mesh.node(i).position), "Failed containment for mesh node %i @ %s" % (i, mesh.node(i).position)) return