def test04_sample_direct(variant_scalar_rgb): from mitsuba.core.xml import load_string from mitsuba.core import Ray3f from mitsuba.render import Interaction3f if mitsuba.core.MTS_ENABLE_EMBREE: pytest.skip("EMBREE enabled") sphere = load_string('<shape type="sphere" version="2.0.0"/>') def sample_cone(sample, cos_theta_max): cos_theta = (1 - sample[1]) + sample[1] * cos_theta_max sin_theta = ek.sqrt(1 - cos_theta * cos_theta) phi = 2 * ek.pi * sample[0] s, c = ek.sin(phi), ek.cos(phi) return [c * sin_theta, s * sin_theta, cos_theta] it = Interaction3f.zero() it.p = [0, 0, -3] it.t = 0 sin_cone_angle = 1.0 / it.p[2] cos_cone_angle = ek.sqrt(1 - sin_cone_angle**2) for xi_1 in ek.linspace(Float, 0, 1, 10): for xi_2 in ek.linspace(Float, 1e-3, 1 - 1e-3, 10): sample = sphere.sample_direction(it, [xi_2, 1 - xi_1]) d = sample_cone([xi_1, xi_2], cos_cone_angle) its = sphere.ray_intersect(Ray3f(it.p, d, 0, [])) assert ek.allclose(d, sample.d, atol=1e-5, rtol=1e-5) assert ek.allclose(its.t, sample.dist, atol=1e-5, rtol=1e-5) assert ek.allclose(its.p, sample.p, atol=1e-5, rtol=1e-5)
def test01_coordinate_system(variant_scalar_rgb): from mitsuba.core import coordinate_system, warp def branchless_onb(n): """ Building an Orthonormal Basis, Revisited Tom Duff, James Burgess, Per Christensen, Christophe Hery, Andrew Kensler, Max Liani, and Ryusuke Villemin """ sign = ek.copysign(1.0, n[2]) a = -1.0 / (sign + n[2]) b = n[0] * n[1] * a return ( [1.0 + sign * n[0] * n[0] * a, sign * b, -sign * n[0]], [b, sign + n[1] * n[1] * a, -n[1]] ) a = [0.70710678, -0. , -0.70710678] b = [-0., 1., 0.] assert ek.allclose( branchless_onb([ek.sqrt(0.5), 0, ek.sqrt(0.5)]), (a, b), atol=1e-6) assert ek.allclose( coordinate_system([ek.sqrt(0.5), 0, ek.sqrt(0.5)]), (a, b), atol=1e-6) for u in ek.linspace(Float, 0, 1, 10): for v in ek.linspace(Float, 0, 1, 10): n = warp.square_to_uniform_sphere([u, v]) s1, t1 = branchless_onb(n) s2, t2 = coordinate_system(n) assert ek.allclose(s1, s2, atol=1e-6) assert ek.allclose(t1, t2, atol=1e-6)
def check_inverse(func, inverse): for x in ek.linspace(Float, 1e-6, 1-1e-6, 10): for y in ek.linspace(Float, 1e-6, 1-1e-6, 10): p1 = np.array([x, y]) p2 = func(p1) p3 = inverse(p2) assert(ek.allclose(p1, p3, atol=1e-5))
def test51_scatter_reduce_fwd_eager(m): with EagerMode(): for i in range(3): idx1 = ek.arange(m.UInt, 5) idx2 = ek.arange(m.UInt, 4) + 3 x = ek.linspace(m.Float, 0, 1, 5) y = ek.linspace(m.Float, 1, 2, 4) buf = ek.zero(m.Float, 10) if i % 2 == 0: ek.enable_grad(buf) ek.set_grad(buf, 1) if i // 2 == 0: ek.enable_grad(x, y) ek.set_grad(x, 1) ek.set_grad(y, 1) x.label = "x" y.label = "y" buf.label = "buf" buf2 = m.Float(buf) ek.scatter_reduce(ek.ReduceOp.Add, buf2, x, idx1) ek.scatter_reduce(ek.ReduceOp.Add, buf2, y, idx2) s = ek.dot_async(buf2, buf2) # Verified against Mathematica assert ek.allclose(ek.detach(s), 15.5972) assert ek.allclose(ek.grad(s), (25.1667 if i // 2 == 0 else 0) + (17 if i % 2 == 0 else 0))
def test18_irrcont_simple_function(variant_packet_rgb): # Reference from Mathematica from mitsuba.core import IrregularContinuousDistribution, Float d = IrregularContinuousDistribution([1, 1.5, 1.8, 5], [1, 3, 0, 1]) assert ek.allclose(d.integral(), 3.05) assert ek.allclose(d.eval_pdf([0, 1, 2, 3, 4, 5, 6]), [0, 1, 0.0625, 0.375, 0.6875, 1, 0]) assert ek.allclose(d.eval_cdf([0, 1, 2, 3, 4, 5, 6]), [0, 0, 1.45625, 1.675, 2.20625, 3.05, 3.05]) assert ek.allclose(d.sample(ek.linspace(Float, 0, 1, 11)), [ 1., 1.21368, 1.35622, 1.47111, 1.58552, 2.49282, 3.35949, 3.8938, 4.31714, 4.67889, 5. ]) assert ek.allclose(d.sample_pdf(ek.linspace(Float, 0, 1, 11)), ([ 1., 1.21368, 1.35622, 1.47111, 1.58552, 2.49282, 3.35949, 3.8938, 4.31714, 4.67889, 5. ], Float([ 1., 1.85472, 2.42487, 2.88444, 2.14476, 0.216506, 0.48734, 0.654313, 0.786607, 0.899653, 1. ]) * d.normalization()))
def test04_sample_direct(variant_scalar_rgb): from mitsuba.core import xml, Ray3f from mitsuba.render import Interaction3f sphere = xml.load_dict({"type": "sphere"}) def sample_cone(sample, cos_theta_max): cos_theta = (1 - sample[1]) + sample[1] * cos_theta_max sin_theta = ek.sqrt(1 - cos_theta * cos_theta) phi = 2 * ek.pi * sample[0] s, c = ek.sin(phi), ek.cos(phi) return [c * sin_theta, s * sin_theta, cos_theta] it = Interaction3f.zero() it.p = [0, 0, -3] it.t = 0 sin_cone_angle = 1.0 / it.p[2] cos_cone_angle = ek.sqrt(1 - sin_cone_angle**2) for xi_1 in ek.linspace(Float, 0, 1, 10): for xi_2 in ek.linspace(Float, 1e-3, 1 - 1e-3, 10): sample = sphere.sample_direction(it, [xi_2, 1 - xi_1]) d = sample_cone([xi_1, xi_2], cos_cone_angle) its = sphere.ray_intersect(Ray3f(it.p, d, 0, [])) assert ek.allclose(d, sample.d, atol=1e-5, rtol=1e-5) assert ek.allclose(its.t, sample.dist, atol=1e-5, rtol=1e-5) assert ek.allclose(its.p, sample.p, atol=1e-5, rtol=1e-5)
def test03_ray_intersect(variant_scalar_rgb): from mitsuba.core import xml, Ray3f, Transform4f for r in [1, 2, 4]: for l in [1, 5]: s = xml.load_dict({ "type": "scene", "foo": { "type": "cylinder", "to_world": Transform4f.scale((r, r, l)) } }) # grid size n = 10 for x in ek.linspace(Float, -1, 1, n): for z in ek.linspace(Float, -1, 1, n): x = 1.1 * r * x z = 1.1 * l * z ray = Ray3f(o=[x, -10, z], d=[0, 1, 0], time=0.0, wavelengths=[]) si_found = s.ray_test(ray) si = s.ray_intersect(ray) assert si_found == si.is_valid() assert si_found == ek.allclose(si.p[0]**2 + si.p[1]**2, r**2) if si_found: ray = Ray3f(o=[x, -10, z], d=[0, 1, 0], time=0.0, wavelengths=[]) si = s.ray_intersect(ray) ray_u = Ray3f(ray) ray_v = Ray3f(ray) eps = 1e-4 ray_u.o += si.dp_du * eps ray_v.o += si.dp_dv * eps si_u = s.ray_intersect(ray_u) si_v = s.ray_intersect(ray_v) dn = si.shape.normal_derivative(si, True, True) if si_u.is_valid(): dp_du = (si_u.p - si.p) / eps dn_du = (si_u.n - si.n) / eps assert ek.allclose(dp_du, si.dp_du, atol=2e-2) assert ek.allclose(dn_du, dn[0], atol=2e-2) if si_v.is_valid(): dp_dv = (si_v.p - si.p) / eps dn_dv = (si_v.n - si.n) / eps assert ek.allclose(dp_dv, si.dp_dv, atol=2e-2) assert ek.allclose(dn_dv, dn[1], atol=2e-2)
def test10_meshgrid(cname): t = get_class(cname) import numpy as np a = ek.linspace(t, 0, 1, 3) b = ek.linspace(t, 0, 1, 4) c, d = ek.meshgrid(a, b) ek.schedule(c, d) cn, dn = np.meshgrid(a.numpy(), b.numpy()) assert ek.allclose(c.numpy(), cn.ravel()) assert ek.allclose(d.numpy(), dn.ravel())
def test03_composite_simpson(variant_scalar_rgb): from mitsuba.core.quad import composite_simpson assert ek.allclose( composite_simpson(3), [ek.linspace(Float, -1, 1, 3), [1.0 / 3.0, 4.0 / 3.0, 1.0 / 3.0]]) assert ek.allclose(composite_simpson(5), [ ek.linspace(Float, -1, 1, 5), [.5 / 3.0, 2 / 3.0, 1 / 3.0, 2 / 3.0, .5 / 3.0] ])
def test03_ray_intersect(variant_scalar_rgb): from mitsuba.core import Ray3f if mitsuba.core.MTS_ENABLE_EMBREE: pytest.skip("EMBREE enabled") for r in [1, 2, 4]: for l in [1, 5]: s = example_scene((r, r, l)) # grid size n = 10 xx = ek.linspace(Float, -1, 1, n) zz = ek.linspace(Float, -1, 1, n) for x in xx: for z in zz: x = 1.1*r*x z = 1.1*l*z ray = Ray3f(o=[x, -10, z], d=[0, 1, 0], time=0.0, wavelengths=[]) si_found = s.ray_test(ray) si = s.ray_intersect(ray) assert si_found == si.is_valid() assert si_found == ek.allclose(si.p[0]**2 + si.p[1]**2, r**2) if si_found: ray = Ray3f(o=[x, -10, z], d=[0, 1, 0], time=0.0, wavelengths=[]) si = s.ray_intersect(ray) ray_u = Ray3f(ray) ray_v = Ray3f(ray) eps = 1e-4 ray_u.o += si.dp_du * eps ray_v.o += si.dp_dv * eps si_u = s.ray_intersect(ray_u) si_v = s.ray_intersect(ray_v) dn = si.shape.normal_derivative(si, True, True) if si_u.is_valid(): dp_du = (si_u.p - si.p) / eps dn_du = (si_u.n - si.n) / eps assert ek.allclose(dp_du, si.dp_du, atol=2e-2) assert ek.allclose(dn_du, dn[0], atol=2e-2) if si_v.is_valid(): dp_dv = (si_v.p - si.p) / eps dn_dv = (si_v.n - si.n) / eps assert ek.allclose(dp_dv, si.dp_dv, atol=2e-2) assert ek.allclose(dn_dv, dn[1], atol=2e-2)
def test04_composite_simpson_38(variant_scalar_rgb): from mitsuba.core.quad import composite_simpson_38 assert ek.allclose( composite_simpson_38(4), [ek.linspace(Float, -1, 1, 4), [0.25, 0.75, 0.75, 0.25]]) assert ek.allclose(composite_simpson_38(7), [ ek.linspace(Float, -1, 1, 7), [0.125, 0.375, 0.375, 0.25, 0.375, 0.375, 0.125] ], atol=1e-6)
def get_bxdf_i(args): # parallel get_bxdf_s ret = np.zeros((args.ti[2], args.pi[2], args.ts[2], args.ps[2]), dtype=float) d2r = ek.pi / 180 theta_i, phi_i = ek.meshgrid( ek.linspace(Float, d2r * args.ti[0], d2r * args.ti[1], args.ti[2]), ek.linspace(Float, d2r * args.pi[0], d2r * args.pi[1], args.pi[2])) for i in range(args.ti[2]): for j in range(args.pi[2]): k = get_bxdf_s(args, theta_i[i], phi_i[j]) ret[i, j, :, :] = k return ret
def tabulate_pdf(self): """ Numerically integrate the provided probability density function over each cell to generate an array resembling the histogram computed by ``tabulate_histogram()``. The function uses the trapezoid rule over intervals discretized into ``self.ires`` separate function evaluations. """ from mitsuba.core import Float, Vector2f, ScalarVector2f extents = self.bounds.extents() endpoint = self.bounds.max - extents / ScalarVector2f(self.res) # Compute a set of nodes where the PDF should be evaluated x, y = ek.meshgrid( ek.linspace(Float, self.bounds.min.x, endpoint.x, self.res.x), ek.linspace(Float, self.bounds.min.y, endpoint.y, self.res.y)) endpoint = extents / ScalarVector2f(self.res) eps = 1e-4 nx = ek.linspace(Float, eps, endpoint.x * (1 - eps), self.ires) ny = ek.linspace(Float, eps, endpoint.y * (1 - eps), self.ires) wx = [1 / (self.ires - 1)] * self.ires wy = [1 / (self.ires - 1)] * self.ires wx[0] = wx[-1] = wx[0] * .5 wy[0] = wy[-1] = wy[0] * .5 integral = 0 self.histogram_start = time.time() for yi, dy in enumerate(ny): for xi, dx in enumerate(nx): xy = self.domain.map_forward(Vector2f(x + dx, y + dy)) pdf = self.pdf_func(xy) integral = ek.fmadd(pdf, wx[xi] * wy[yi], integral) self.histogram_end = time.time() self.pdf = integral * (ek.hprod(extents / ScalarVector2f(self.res)) * self.sample_count) # A few sanity checks pdf_min = ek.hmin(self.pdf) / self.sample_count if not pdf_min >= 0: self._log('Failure: Encountered a cell with a ' 'negative PDF value: %f' % pdf_min) self.fail = True self.pdf_sum = ek.hsum(self.pdf) / self.sample_count if self.pdf_sum > 1.1: self._log('Failure: PDF integrates to a value greater ' 'than 1.0: %f' % self.pdf_sum) self.fail = True
def test20_scatter_add_rev(m): for i in range(3): idx1 = ek.arange(m.UInt, 5) idx2 = ek.arange(m.UInt, 4) + 3 x = ek.linspace(m.Float, 0, 1, 5) y = ek.linspace(m.Float, 1, 2, 4) buf = ek.zero(m.Float, 10) if i % 2 == 0: ek.enable_grad(buf) if i // 2 == 0: ek.enable_grad(x, y) x.label = "x" y.label = "y" buf.label = "buf" buf2 = m.Float(buf) ek.scatter_add(buf2, x, idx1) ek.scatter_add(buf2, y, idx2) ref_buf = m.Float(0.0000, 0.2500, 0.5000, 1.7500, 2.3333, 1.6667, 2.0000, 0.0000, 0.0000, 0.0000) assert ek.allclose(ref_buf, buf2, atol=1e-4) assert ek.allclose(ref_buf, buf, atol=1e-4) s = ek.dot_async(buf2, buf2) print(ek.graphviz_str(s)) ek.backward(s) ref_x = m.Float(0.0000, 0.5000, 1.0000, 3.5000, 4.6667) ref_y = m.Float(3.5000, 4.6667, 3.3333, 4.0000) if i // 2 == 0: assert ek.allclose(ek.grad(y), ek.detach(ref_y), atol=1e-4) assert ek.allclose(ek.grad(x), ek.detach(ref_x), atol=1e-4) else: assert ek.grad(x) == 0 assert ek.grad(y) == 0 if i % 2 == 0: assert ek.allclose(ek.grad(buf), ek.detach(ref_buf) * 2, atol=1e-4) else: assert ek.grad(buf) == 0
def test03_smith_g1_beckmann(variant_packet_rgb): from mitsuba.core import Vector3f from mitsuba.render import MicrofacetDistribution, MicrofacetType # Compare against data obtained from previous Mitsuba v0.6 implementation mdf = MicrofacetDistribution(MicrofacetType.Beckmann, 0.1, 0.3, False) mdf_i = MicrofacetDistribution(MicrofacetType.Beckmann, 0.1, False) steps = 20 theta = ek.linspace(Float, ek.pi / 3, ek.pi / 2, steps) phi = Float.full(ek.pi / 2, steps) cos_theta, sin_theta = ek.cos(theta), ek.sin(theta) cos_phi, sin_phi = ek.cos(phi), ek.sin(phi) v = [cos_phi * sin_theta, sin_phi * sin_theta, cos_theta] wi = Vector3f(0, 0, 1) ek.set_slices(wi, steps) assert np.allclose(mdf.smith_g1(v, wi), [ 1.0000000e+00, 1.0000000e+00, 1.0000000e+00, 1.0000523e+00, 9.9941480e-01, 9.9757767e-01, 9.9420297e-01, 9.8884594e-01, 9.8091525e-01, 9.6961778e-01, 9.5387781e-01, 9.3222123e-01, 9.0260512e-01, 8.6216795e-01, 8.0686140e-01, 7.3091686e-01, 6.2609726e-01, 4.8074335e-01, 2.7883825e-01, 1.9197471e-06 ]) assert ek.allclose(mdf_i.smith_g1(v, wi), [ 1.0000000e+00, 1.0000000e+00, 1.0000000e+00, 1.0000000e+00, 1.0000000e+00, 1.0000000e+00, 1.0000000e+00, 1.0000000e+00, 1.0000000e+00, 1.0000000e+00, 1.0000000e+00, 1.0000000e+00, 1.0000000e+00, 1.0000000e+00, 9.9828446e-01, 9.8627287e-01, 9.5088160e-01, 8.5989666e-01, 6.2535185e-01, 5.7592310e-06 ]) steps = 20 theta = Float.full(ek.pi / 2 * 0.98, steps) phi = ek.linspace(Float, 0, 2 * ek.pi, steps) cos_theta, sin_theta = ek.cos(theta), ek.sin(theta) cos_phi, sin_phi = ek.cos(phi), ek.sin(phi) v = [cos_phi * sin_theta, sin_phi * sin_theta, cos_theta] assert ek.allclose(mdf.smith_g1(v, wi), [ 0.67333597, 0.56164336, 0.42798978, 0.35298213, 0.31838724, 0.31201753, 0.33166203, 0.38421196, 0.48717275, 0.63746351, 0.63746351, 0.48717275, 0.38421196, 0.33166203, 0.31201753, 0.31838724, 0.35298213, 0.42798978, 0.56164336, 0.67333597 ]) assert ek.allclose(mdf_i.smith_g1(v, wi), Float.full(0.67333597, steps))
def test19_gather_fwd(m): x = ek.linspace(m.Float, -1, 1, 10) ek.enable_grad(x) y = ek.gather(m.Float, x * x, m.UInt(1, 1, 2, 3)) ek.forward(x) ref = [-1.55556, -1.55556, -1.11111, -0.666667] assert ek.allclose(ek.grad(y), ref)
def test02_fresnel_polarized_packet(variant_packet_rgb): from mitsuba.render import fresnel cos_theta_i = ek.linspace(Float, -1, 1, 20) F, cos_theta_t, _, scale = fresnel(cos_theta_i, 1) assert ek.all(F == Float.zero(20)) assert ek.allclose(cos_theta_t, -cos_theta_i, atol=5e-7)
def test15_test_avx512_approx(): Float = get_class('enoki.llvm.Float') x = ek.linspace(Float, 0, 10, 1000) o = ek.full(Float, 1, 1000) assert ek.allclose(ek.rsqrt(x), o / ek.sqrt(x), rtol=2e-7, atol=0) assert ek.allclose(ek.rcp(x), o / x, rtol=2e-7, atol=0)
def test22_scatter_fwd(m): x = m.Float(4.0) ek.enable_grad(x) values = x * x * ek.linspace(m.Float, 1, 4, 4) idx = 2 * ek.arange(m.UInt32, 4) buf = ek.zero(m.Float, 10) ek.scatter(buf, values, idx) assert ek.grad_enabled(buf) ref = [16.0, 0.0, 32.0, 0.0, 48.0, 0.0, 64.0, 0.0, 0.0, 0.0] assert ek.allclose(buf, ref) ek.forward(x, retain_graph=True) grad = ek.grad(buf) ref_grad = [8.0, 0.0, 16.0, 0.0, 24.0, 0.0, 32.0, 0.0, 0.0, 0.0] assert ek.allclose(grad, ref_grad) # Overwrite first value with non-diff value, resulting gradient entry should be 0 y = m.Float(3) idx = m.UInt32(0) ek.scatter(buf, y, idx) ref = [3.0, 0.0, 32.0, 0.0, 48.0, 0.0, 64.0, 0.0, 0.0, 0.0] assert ek.allclose(buf, ref) ek.forward(x) grad = ek.grad(buf) ref_grad = [0.0, 0.0, 16.0, 0.0, 24.0, 0.0, 32.0, 0.0, 0.0, 0.0] assert ek.allclose(grad, ref_grad)
def test17_cos(m): x = ek.linspace(m.Float, 0.01, 10, 10) ek.enable_grad(x) y = ek.cos(x) ek.backward(y) assert ek.allclose(ek.detach(y), ek.cos(ek.detach(x))) assert ek.allclose(ek.grad(x), -ek.sin(ek.detach(x)))
def test05_sample_ggx(variant_packet_rgb): from mitsuba.render import MicrofacetDistribution, MicrofacetType mdf = MicrofacetDistribution(MicrofacetType.GGX, 0.1, 0.3, False) # Compare against data obtained from previous Mitsuba v0.6 implementation steps = 6 u = ek.linspace(Float, 0, 1, steps) u1, u2 = ek.meshgrid(u, u) u = [u1, u2] wi = np.tile([0, 0, 1], (steps * steps, 1)) result = mdf.sample(wi, u) ref = ((np.array([[0.00000000e+00, 0.00000000e+00, 1.00000000e+00], [4.99384739e-02, 1.30972797e-08, 9.98752296e-01], [8.13788623e-02, 2.13430980e-08, 9.96683240e-01], [1.21566132e-01, 3.18829443e-08, 9.92583334e-01], [1.96116075e-01, 5.14350340e-08, 9.80580688e-01], [1.00000000e+00, 2.62268316e-07, 0.00000000e+00], [0.00000000e+00, 0.00000000e+00, 1.00000000e+00], [1.52942007e-02, 1.41212299e-01, 9.89861190e-01], [2.45656986e-02, 2.26816610e-01, 9.73627627e-01], [3.57053429e-02, 3.29669625e-01, 9.43420947e-01], [5.36015145e-02, 4.94906068e-01, 8.67291689e-01], [1.07676744e-01, 9.94185984e-01, 0.00000000e+00], [-0.00000000e+00, 0.00000000e+00, 1.00000000e+00], [-4.02617380e-02, 8.77555013e-02, 9.95328069e-01], [-6.52425364e-02, 1.42204270e-01, 9.87684846e-01], [-9.64000970e-02, 2.10116088e-01, 9.72912252e-01], [-1.50845990e-01, 3.28787714e-01, 9.32278991e-01], [-4.17001039e-01, 9.08905983e-01, 0.00000000e+00], [-0.00000000e+00, -0.00000000e+00, 1.00000000e+00], [-4.02616598e-02, -8.77555385e-02, 9.95328069e-01], [-6.52425662e-02, -1.42204687e-01, 9.87684786e-01], [-9.64000225e-02, -2.10116416e-01, 9.72912192e-01], [-1.50845826e-01, -3.28788161e-01, 9.32278872e-01], [-4.17000234e-01, -9.08906400e-01, 0.00000000e+00], [0.00000000e+00, -0.00000000e+00, 1.00000000e+00], [1.52942603e-02, -1.41212285e-01, 9.89861190e-01], [2.45657954e-02, -2.26816595e-01, 9.73627627e-01], [3.57054621e-02, -3.29669416e-01, 9.43421006e-01], [5.36017120e-02, -4.94905949e-01, 8.67291749e-01], [1.07677162e-01, -9.94185925e-01, 0.00000000e+00], [0.00000000e+00, 0.00000000e+00, 1.00000000e+00], [4.99384739e-02, 8.73152040e-09, 9.98752296e-01], [8.13788623e-02, 1.42287320e-08, 9.96683240e-01], [1.21566132e-01, 2.12552980e-08, 9.92583334e-01], [1.96116075e-01, 3.42900250e-08, 9.80580688e-01], [1.00000000e+00, 1.74845553e-07, 0.00000000e+00]]), np.array([ 10.61032867, 6.81609201, 3.85797882, 1.73599267, 0.45013079, 0., 10.61032867, 7.00141668, 4.13859272, 2.02177191, 0.65056872, 0., 10.61032867, 6.88668203, 3.96438813, 1.84343493, 0.52378261, 0., 10.61032867, 6.88668203, 3.96438861, 1.84343517, 0.52378279, 0., 10.61032867, 7.00141668, 4.13859272, 2.02177191, 0.65056866, 0., 10.61032867, 6.81609201, 3.85797882, 1.73599267, 0.45013079, 0. ]))) assert ek.allclose(ref[0], result[0], atol=5e-4) assert ek.allclose(ref[1], result[1], atol=1e-4)
def check_vectorization(func_str, wrapper = (lambda f: lambda x: f(x)) , resolution = 2): """ Helper routine which compares evaluations of the vectorized and non-vectorized version of a warping routine """ import importlib mitsuba.set_variant('scalar_rgb') func = wrapper(getattr(importlib.import_module('mitsuba.core').warp, func_str)) pdf_func = wrapper(getattr(importlib.import_module('mitsuba.core').warp, func_str + "_pdf")) try: mitsuba.set_variant('packet_rgb') except: pytest.skip("packet_rgb mode not enabled") func_vec = wrapper(getattr(importlib.import_module('mitsuba.core').warp, func_str)) pdf_func_vec = wrapper(getattr(importlib.import_module('mitsuba.core').warp, func_str + "_pdf")) from mitsuba.core import Vector2f # Generate resolution^2 test points on a 2D grid t = ek.linspace(Float, 1e-3, 1, resolution) x, y = ek.meshgrid(t, t) samples = Vector2f(x, y) # Run the sampling routine result = func_vec(samples) # Evaluate the PDF pdf = pdf_func_vec(result) # Check against the scalar version for i in range(resolution): assert ek.allclose(result.numpy()[i, :], func(samples.numpy()[i, :]), atol=1e-4) assert ek.allclose(pdf.numpy()[i], pdf_func(result.numpy()[i, :]), atol=1e-6)
def test06_hsum_0_fwd(m): x = ek.linspace(m.Float, 0, 1, 10) ek.enable_grad(x) y = ek.hsum_async(x * x) ek.forward(x) assert len(y) == 1 and ek.allclose(ek.detach(y), 95.0 / 27.0) assert len(ek.grad(y)) == 1 and ek.allclose(ek.grad(y), 10)
def test05_hsum_0_rev(m): x = ek.linspace(m.Float, 0, 1, 10) ek.enable_grad(x) y = ek.hsum_async(x * x) ek.backward(y) assert len(y) == 1 and ek.allclose(y, 95.0 / 27.0) assert ek.allclose(ek.grad(x), 2 * ek.detach(x))
def test50_gather_fwd_eager(m): with EagerMode(): x = ek.linspace(m.Float, -1, 1, 10) ek.enable_grad(x) ek.set_grad(x, 1) y = ek.gather(m.Float, x * x, m.UInt(1, 1, 2, 3)) ref = [-1.55556, -1.55556, -1.11111, -0.666667] assert ek.allclose(ek.grad(y), ref)
def test09_hsum_2_rev(m): x = ek.linspace(m.Float, 0, 1, 11) ek.enable_grad(x) z = ek.hsum_async(ek.hsum_async(x * x) * x * x) ek.backward(z) assert ek.allclose( ek.grad(x), [0., 1.54, 3.08, 4.62, 6.16, 7.7, 9.24, 10.78, 12.32, 13.86, 15.4])
def test18_gather(m): x = ek.linspace(m.Float, -1, 1, 10) ek.enable_grad(x) y = ek.gather(m.Float, x * x, m.UInt(1, 1, 2, 3)) z = ek.hsum_async(y) ek.backward(z) ref = [0, -1.55556 * 2, -1.11111, -0.666667, 0, 0, 0, 0, 0, 0] assert ek.allclose(ek.grad(x), ref)
def test40_safe_functions(m): x = ek.linspace(m.Float, 0, 1, 10) y = ek.linspace(m.Float, -1, 1, 10) z = ek.linspace(m.Float, -1, 1, 10) ek.enable_grad(x, y, z) x2 = ek.safe_sqrt(x) y2 = ek.safe_acos(y) z2 = ek.safe_asin(z) ek.backward(x2) ek.backward(y2) ek.backward(z2) assert ek.grad(x)[0] == 0 assert ek.allclose(ek.grad(x)[1], .5 / ek.sqrt(1 / 9)) assert x[0] == 0 assert ek.all(ek.isfinite(ek.grad(x))) assert ek.all(ek.isfinite(ek.grad(y))) assert ek.all(ek.isfinite(ek.grad(z)))
def test24_log(m): x = ek.linspace(m.Float, 0.01, 1, 10) ek.enable_grad(x) y = ek.log(x * x) ek.backward(y) log_x = ek.log(ek.sqr(ek.detach(x))) assert ek.allclose(y, log_x) assert ek.allclose(ek.grad(x), 2 / ek.detach(x))
def test23_exp(m): x = ek.linspace(m.Float, 0, 1, 10) ek.enable_grad(x) y = ek.exp(x * x) ek.backward(y) exp_x = ek.exp(ek.sqr(ek.detach(x))) assert ek.allclose(y, exp_x) assert ek.allclose(ek.grad(x), 2 * ek.detach(x) * exp_x)