def side(x, y, z): p0 = make_vector3(x, y, z) p0 = p0 / 2.0 * size n0 = -make_vector3(x, y, z) n0 = n0 self.p0 += [p0] self.n0 += [n0]
def numerical_gradient(iobj, pos0, delta_t=0.01 / 10.0 / 10.0, order=5): check_vector3(pos0) assert issubclass(type(iobj), vector3.ImplicitFunction) m = order # sample points: -m,...,-1,0,1,2,...,+m sample_points = range(-m, m + 1) n = m * 2 + 1 x0 = 0 findiff_weights = weights(k=1, x0=x0, xs=np.array(sample_points) * delta_t) pos = repeat_vect3(1, pos0) pos3 = np.tile(pos, (3 * n, 1)) assert not issubclass(pos.dtype.type, np.integer) dx = repeat_vect3(1, make_vector3(1, 0, 0)) dy = repeat_vect3(1, make_vector3(0, 1, 0)) dz = repeat_vect3(1, make_vector3(0, 0, 1)) dxyz = [dx, dy, dz] ci = 0 for d in range(3): for i in sample_points: dd = dxyz[d] pos3[ci, :] = pos3[ci, :] + (dd * delta_t * float(i)) ci += 1 v = iobj.implicitFunction(pos3) v3 = np.reshape(v, (3, n), order='C') Lipchitz_beta = 1 # order. Keep it 1 d0 = np.abs(np.diff(v3, axis=1)) nonsmooth_ness = d0 / (np.abs(delta_t)**Lipchitz_beta) d = np.abs(np.diff(v3, n=1, axis=1)) / np.abs(delta_t) d = d - np.tile(np.mean(d, axis=1, keepdims=True), (1, d.shape[1])) d = np.abs(d) / np.abs(delta_t) d = d - np.tile(np.mean(d, axis=1, keepdims=True), (1, d.shape[1])) if (np.max(np.ravel(nonsmooth_ness))) > 100 * 10: print "warning: nonsmooth ", """ Calculating the numerical derivative using finite difference (convolution with weights) """ # convolusion grad_cnv = np.dot(v3, findiff_weights) # Detecting sharp edges (non-smooth points, i.e. corners and edges and ridges) if np.max(np.abs(grad_cnv)) > 100: pass return grad_cnv.reshape(1, 3)
def side(x, y, z): p0 = make_vector3(x, y, z) p0 = p0 / 2.0 * size n0 = -make_vector3(x, y, z) n0 = n0 self.p0 += [p0] self.n0 += [n0] # print(self.p0[-1]) check_vector3(self.p0[-1]) check_vector3(self.n0[-1]) def norm2(v): return v[0] * v[0] + v[1] * v[1] + v[2] * v[2] assert norm2(self.n0[-1]) - 1 == 0.0
def test_gradients_using_numerical_gradient(self): def blend2(): m1 = np.eye(4) * 1 m1[0:3, 3] = [0, 1, 0] m1[3, 3] = 1 m2 = np.eye(4) * 2 m2[0:3, 3] = [2.5, 0, 0] m2[3, 3] = 1 iobj_v = vector3.SimpleBlend(vector3.Ellipsoid(m1), vector3.Ellipsoid(m2)) return iobj_v iobj_v = blend2() self.check_gradient_function(iobj_v, objname="blend2") examples_list = example_objects.get_all_examples([2]) for example_name in examples_list: sys.stderr.write("example_name = ", example_name) iobj = example_objects.make_example_vectorized(example_name) self.check_gradient_function(iobj, objname=example_name) """ numerical """ x = make_vector3(0, 2, 0) g2 = numerical_gradient(iobj_v, x) g = iobj_v.implicitGradient(repeat_vect3(1, x)) np.set_printoptions( formatter={'all': lambda x: '' + ("%2.19f" % (x, ))}) err = np.sum(np.abs(g - g2), axis=1) err_max = np.max(np.abs(g - g2), axis=1) err_rel = np.sum(np.abs(g - g2), axis=1) / np.mean(np.abs(g)) sys.stderr.write(err, err_max, err_rel) # print(err) self.assertTrue(np.all(err < NUMERICAL_GRADIENT_TOLERANCE))
def french_fries(scale): def rod(): c = vector3.UnitCube1() m2 = np.eye(4) * scale m2[0, 0] = 0.1 * scale m2[1, 1] = 0.1 * scale m2[0:3, 3] = [+0.1 / 2.0 * 2 * scale, +0.1 / 2.0 * 2 * scale, + 1.0 / 2.0 * 2 * scale] m2[3, 3] = 1 iobj = vector3.Transformed(c, m2) # .move(-0.1/2.0, -0.1/2.0, -1.0/2.0) iobj \ .move(-0.2 * scale, -0.2 * scale, 0) \ .resize(2) \ .rotate(10, along=make_vector3(1, 1, 0), units="deg") \ .move(0.5 * scale, 0, 0) return iobj u = None for i in range(18): c = rod().rotate(-30 * i, along=make_vector3(0, 0, 1), units="deg") if u is None: u = c else: u = vector3.CrispUnion(u, c) return u
def cube_example(scale=1.): iobj = vector3.UnitCube1() iobj = vector3.Transformed(iobj) \ .move(-0.1 * scale, -0.1 * scale, -0.1 * scale) .resize(3 * scale) \ .rotate(-20, along=make_vector3(1, 1, 1), units="deg") .move(0.2 * scale, 0, 0) return iobj
def rcube_vec(scale, rotated=True): d = vector3.UnitCube1(size=2.0 * scale) iobj = vector3.Transformed(d) iobj \ .move(-0.2 * scale, -0.2 * scale, 0) \ .resize(0.9) if rotated: iobj.rotate(10 * 2, along=make_vector3(1, 1, 1), units="deg") #iobj.rotate(60, along=make_vector3(1, 1, 1), units="deg") return iobj
def rdice_vec(scale, rotated=True): d = dice(scale) return d iobj = vector3.Transformed(d) iobj \ .move(-0.2 * scale, -0.2 * scale, 0) \ .resize(0.9) iobj.rotate(20, along=make_vector3(1, 1, 1), units="deg") return iobj
def vectors_parallel_and_direction(v1, v2): assert v1.shape == (3, ), str(v1.shape) assert v2.shape == (3, ), str(v2.shape) cross_prod = np.cross(v1, v2) inner_prod = np.dot(np.transpose(v1), v2) are_parallel1 = almost_equal3(cross_prod, make_vector3(0, 0, 0), TOLERANCE) are_directed = (inner_prod > 0) are_parallel2 = np.allclose(cross_prod, np.array([0, 0, 0]), atol=TOLERANCE) return (are_parallel1 and are_parallel2, are_directed)
def rod(): c = vector3.UnitCube1() m2 = np.eye(4) m2[0, 0] = 0.1 * scale m2[1, 1] = 0.1 * scale m2[2, 2] = scale iobj = vector3.Transformed(c, m2) iobj \ .move(-0, -0.3*scale, -1.0*scale) \ .resize(2) \ .rotate(40, along=make_vector3(1, 1, 0), units="deg") \ .move(0.5*scale, 0, 0) return iobj
def rod(): c = vector3.UnitCube1() m2 = np.eye(4) * scale m2[0, 0] = 0.1 * scale m2[1, 1] = 0.1 * scale m2[0:3, 3] = [+0.1 / 2.0 * 2 * scale, +0.1 / 2.0 * 2 * scale, + 1.0 / 2.0 * 2 * scale] m2[3, 3] = 1 iobj = vector3.Transformed(c, m2) # .move(-0.1/2.0, -0.1/2.0, -1.0/2.0) iobj \ .move(-0.2 * scale, -0.2 * scale, 0) \ .resize(2) \ .rotate(10, along=make_vector3(1, 1, 0), units="deg") \ .move(0.5 * scale, 0, 0) return iobj
def check_gradient_function(self, iobj, tolerance=NUMERICAL_GRADIENT_TOLERANCE, objname=None): """testing the gradient on 100 random points """ assert (-1) * -tolerance > 0, "should be a number" if iobj is not None: from vector3 import ImplicitFunction assert issubclass(type(iobj), ImplicitFunction) for i in range(100): radius = 10 # 10/5 x = make_random_vector3(radius, 1, type="randn") # [0:3] x = x * np.random.randn() * 5 self.check_gradient_function_point1(iobj, x, tolerance, objname) x = make_vector3(0, 2, 0) self.check_gradient_function_point1(iobj, x, tolerance, objname)
def rods(scale): # the scale needs to be equal to 2 in order to have a nice object def rod(): c = vector3.UnitCube1() m2 = np.eye(4) m2[0, 0] = 0.1 * scale m2[1, 1] = 0.1 * scale m2[2, 2] = scale iobj = vector3.Transformed(c, m2) iobj \ .move(-0, -0.3*scale, -1.0*scale) \ .resize(2) \ .rotate(40, along=make_vector3(1, 1, 0), units="deg") \ .move(0.5*scale, 0, 0) return iobj u = None for i in range(17): c = rod().rotate(-30 * i, along=make_vector3(0, 0, 1), units="deg") if u is None: u = c else: u = vector3.CrispUnion(u, c) return u
def numerical_gradient(iobj, pos0, delta_t=0.01/10.0/10.0, order=5): check_vector3(pos0) assert issubclass(type(iobj), vector3.ImplicitFunction) m = order _VERBOSE = False import finite_diff_weights sample_points = range(-m, m+1) n = m*2+1 x0 = 0 findiff_weights = finite_diff_weights.weights(k=1, x0=x0, xs=np.array(sample_points) * delta_t) pos0_3 = repeat_vect3(1, pos0) pos = np.tile(pos0_3, (3*n, 1)) assert not issubclass(pos.dtype.type, np.integer) dx = repeat_vect3(1, make_vector3(1, 0, 0)) dy = repeat_vect3(1, make_vector3(0, 1, 0)) dz = repeat_vect3(1, make_vector3(0, 0, 1)) dxyz = [dx, dy, dz] ci = 0 for d in range(3): for i in sample_points: dd = dxyz[d] pos[ci, :] = pos[ci, :] + (dd * delta_t * float(i)) ci += 1 v = iobj.implicitFunction(pos) v3 = np.reshape(v, (3, n), order='C') Lipchitz_beta = 1 d0 = np.abs(np.diff(v3, axis=1)) nonsmooth_ness = d0 / (np.abs(delta_t)**Lipchitz_beta) d = np.abs(np.diff(v3, n=1, axis=1)) / np.abs(delta_t) d = d - np.tile(np.mean(d, axis=1, keepdims=True), (1, d.shape[1])) d = np.abs(d) / np.abs(delta_t) d = d - np.tile(np.mean(d, axis=1, keepdims=True), (1, d.shape[1])) if(np.max(np.ravel(nonsmooth_ness))) > 100*10: print "warning: nonsmooth ", """ Calculating the numerical derivative using finite difference (convolution with weights) """ grad_cnv = np.dot(v3, findiff_weights) if np.max(np.abs(grad_cnv)) > 100: pass if _VERBOSE: np.set_printoptions(formatter={'all': lambda x: ''+("%2.19f" % (x,))}) """ Calculating the numerical derivative using 'mean of diff' """ grad_mean = np.mean(-np.diff(v3, axis=1) / delta_t, axis=1) if _VERBOSE: sys.stderr.write("grad_mean: ", grad_mean) sys.stderr.write("grad_convolusion: ", grad_cnv) if False: g = iobj.implicitGradient(pos0_3) if _VERBOSE: sys.stderr.write("grad_analytical: ", g) sys.stderr.write("Errors:") sys.stderr.write("conv error: ", g - grad_cnv) sys.stderr.write("to be continued") return grad_cnv
def numerical_gradient_vectorized_v2(iobj, pos0, delta_t=0.01 / 100., order=5): # not useful here because we are working with a vector whose dimension are(3,1) """ A proper vectorized implementation. See numerical_gradient() """ # Note: 0.1 is not enough for delta_t check_vector3_vectorized(pos0) assert issubclass(type(iobj), vector3.ImplicitFunctionVectorized) assert pos0.ndim == 2 if pos0.shape[0] == 0: return np.zeros((0, 3)) m = order # sample points: -m,...,-1,0,1,2,...,+m sample_points = range(-m, m + 1) n = m * 2 + 1 x0 = 0 findiff_weights = weights(k=1, x0=x0, xs=np.array(sample_points) * delta_t) del x0 assert n < 20 pos0_3 = pos0[:, np.newaxis, :] pos = np.tile(pos0_3, (1, 3 * n, 1)) assert not issubclass(pos.dtype.type, np.integer) dx = make_vector3(1, 0, 0)[np.newaxis, np.newaxis, :] dy = make_vector3(0, 1, 0)[np.newaxis, np.newaxis, :] dz = make_vector3(0, 0, 1)[np.newaxis, np.newaxis, :] dxyz = [dx, dy, dz] ci = 0 for d in range(3): dd = dxyz[d] for i in sample_points: pos[:, ci, :] = pos[:, ci, :] + (dd * (delta_t * float(i))) assert ci < 3 * n ci += 1 vsize = pos0.shape[0] v = iobj.implicitFunction(pos.reshape((vsize * 3 * n), 3)) # v .shape: (3,11) v3 = np.reshape(v, (vsize, 3, n), order='C') # v3 .shape: (11,) if True: Lipchitz_B = 50 # Lipschitz constant Lipchitz_beta = 1 # order. Keep it 1 b_h_beta = Lipchitz_B * (np.abs(delta_t)**Lipchitz_beta) d0 = np.abs(np.diff(v3, axis=1 + 1)) nonsmooth_ness = d0 / (np.abs(delta_t)**Lipchitz_beta) del d0, b_h_beta, Lipchitz_beta, Lipchitz_B # print nonsmooth_ness.shape # set_trace() if (np.max(np.ravel(nonsmooth_ness))) > 100 * 10: print "warning: nonsmooth ", del nonsmooth_ness if False: d = np.abs(np.diff(v3, n=1, axis=1 + 1)) / np.abs(delta_t) d = d - np.tile(np.mean(d, axis=1 + 1, keepdims=True), (1, 1, d.shape[1 + 1])) d = np.abs(d) / np.abs(delta_t) d = d - np.tile(np.mean(d, axis=1 + 1, keepdims=True), (1, 1, d.shape[1 + 1])) del d """ Calculating the numerical derivative using finite difference (convolution with weights) """ # convolusion grad_cnv = np.dot( v3, findiff_weights ) # "sum product over the last axis of a and the second-to-last of b" assert not np.any(np.isnan(grad_cnv), axis=None) return grad_cnv
def test_ellipsoid_certain_points(self): """ Ellipsoid using vectorized calculations """ N = 10 _x = make_vector3(0, 0, 1) xa = repeat_vect3(N, _x) m = np.eye(4) # makeMatrix4( 1,0,0,0, 0,1,0,0, 0,0,1,0 ) m[0, 0] = 1 ga2 = repeat_vect3(N, make_vector3(0, 0, -1)) self.ellipsoid_point_and_gradient_vectorized(m, xa, ga2) m = np.eye(4) self.ellipsoid_point_and_gradient_vectorized( m, repeat_vect3(N, make_vector3(0, 1, 0)), repeat_vect3(N, make_vector3(0, -1, 0))) m = np.eye(4) self.ellipsoid_point_and_gradient_vectorized( m, repeat_vect3(N, make_vector3(1, 0, 0)), repeat_vect3(N, make_vector3(-1, 0, 0))) xa = repeat_vect3(N, make_vector3(0, 0, 2)) m = np.eye(4) m[2, 2] = 2 self.ellipsoid_point_and_gradient_vectorized( m, xa, repeat_vect3(N, make_vector3(0, 0, -1))) xa = repeat_vect3(N, make_vector3(2, 0, 0)) m = np.eye(4) m[0, 0] = 2 self.ellipsoid_point_and_gradient_vectorized( m, xa, repeat_vect3(N, make_vector3(-1, 0, 0))) xa = repeat_vect3(N, make_vector3(0, 2, 0)) m = np.eye(4) m[0, 0] = 2 m[1, 1] = 2 m[2, 2] = 2 self.ellipsoid_point_and_gradient_vectorized( m, xa, repeat_vect3(N, make_vector3(0, -2, 0)))