def test_scale_bkg_abeles(self): s = self.structure.slabs()[..., :4] calcs = [] for backend in BACKENDS: with use_reflect_backend(backend) as abeles: calc = abeles(self.qvals, s, scale=2.0) calcs.append(calc) for calc in calcs[1:]: assert_allclose(calc, calcs[0]) calcs = [] for backend in BACKENDS: with use_reflect_backend(backend) as abeles: calc = abeles(self.qvals, s, scale=0.5, bkg=0.1) calcs.append(calc) for calc in calcs[1:]: assert_allclose(calc, calcs[0]) calcs = [] for backend in BACKENDS: with use_reflect_backend(backend) as abeles: calc = abeles(self.qvals, s, scale=0.5, bkg=0.1, threads=2) calcs.append(calc) for calc in calcs[1:]: assert_allclose(calc, calcs[0])
def test_compare_abeles2(self, backend): # test two layer system against the python implementation layer2 = np.array([ [0, 2.07, 0.01, 3], [10, 3.47, 0.01, 3], [100, 1.0, 0.01, 4], [0, 6.36, 0.1, 3], ]) with use_reflect_backend("python") as abeles: calc1 = abeles(self.qvals, layer2, scale=0.99, bkg=1e-8) with use_reflect_backend(backend) as abeles: calc2 = abeles(self.qvals, layer2, scale=0.99, bkg=1e-8) assert_almost_equal(calc1, calc2)
def test_multilayer(self): x = np.geomspace(0.005, 0.5, 101) air = np.array([0, 0, 0, 0]) unit_cell = np.array([[30, -2.0, 0, 3], [70, 8.0, 0, 3]]) backing = np.array([0, 2.07, 0.0001, 3]) def get_w(repeats=1): if repeats: filling = np.vstack([unit_cell] * repeats) return np.vstack([air, filling, backing]) else: return np.vstack([air, backing]) backends = list(BACKENDS) backends.remove("python") f_python = reflect_model.get_reflect_backend("python") for i in range(40): w = get_w(i) canonical_r = f_python(x, w) for backend in backends: with use_reflect_backend(backend) as abeles: calc = abeles(x, w) try: assert_allclose(calc, canonical_r, atol=5.0e-15, rtol=8.0e-15) except AssertionError as e: print(backend, i) raise e
def test_abeles(self, backend): slabs = self.structure.slabs()[..., :4] # test reflectivity calculation with values generated from Motofit with use_reflect_backend(backend) as abeles: calc = abeles(self.qvals, slabs) assert_almost_equal(calc, self.rvals)
def test_abeles_absorption(self, backend): # https://github.com/andyfaff/refl1d_analysis/tree/master/notebooks q = np.linspace(0.008, 0.05, 500) depth = [0, 850, 0] rho = [2.067, 4.3, 6.0] irho_zero = [0.0, 0.1, 0.0] refnx_sigma = [np.nan, 35, 5.0] w_zero = np.c_[depth, rho, irho_zero, refnx_sigma] with use_reflect_backend("python") as abeles: calc1 = abeles(q, w_zero) with use_reflect_backend(backend) as abeles: calc2 = abeles(q, w_zero) assert_almost_equal(calc1, calc2)
def test_abeles_multithreaded(self): slabs = self.structure.slabs()[..., :4] for backend in BACKENDS: # test reflectivity calculation with values generated from Motofit with use_reflect_backend(backend) as abeles: calc = abeles(self.qvals, slabs, threads=4) assert_almost_equal(calc, self.rvals)
def test_compare_abeles0(self, backend): # test one layer system against the python implementation layer0 = np.array([[0, 2.07, 0.01, 3], [0, 6.36, 0.1, 3]]) with use_reflect_backend("python") as abeles: calc1 = abeles(self.qvals, layer0, scale=0.99, bkg=1e-8) with use_reflect_backend(backend) as abeles: calc2 = abeles(self.qvals, layer0, scale=0.99, bkg=1e-8) assert_almost_equal(calc1, calc2) # test a negative background with use_reflect_backend("python") as abeles: calc1 = abeles(self.qvals, layer0, scale=0.99, bkg=-5e-7) with use_reflect_backend(backend) as abeles: calc2 = abeles(self.qvals, layer0, scale=0.99, bkg=-5e-7) assert_almost_equal(calc1, calc2)
def test_first_principles(self): # Test a first principles reflectivity calculation, rather than # relying on a previous calculation from Motofit code. # Here we only examine Fresnel reflectivity from an infinitely # sharp interface, we do not examine a rough surface. This is # tested by profile slicing in test_structure. def kn(q, sld_layer, sld_fronting): # wave vector in a given layer kvec = np.zeros_like(q, np.complex128) sld = complex(sld_layer - sld_fronting) * 1.0e-6 kvec[:] = np.sqrt(q[:]**2.0 / 4.0 - 4.0 * np.pi * sld) return kvec q = np.linspace(0.001, 1.0, 1001) # Is the fresnel reflectivity correct? sld1 = 2.07 sld2 = 6.36 # first principles calcn kf = kn(q, sld1, sld1) kb = kn(q, sld2, sld1) reflectance = (kf - kb) / (kf + kb) reflectivity = reflectance * np.conj(reflectance) # now from refnx code struct = SLD(sld1)(0, 0) | SLD(sld2)(0, 0) slabs = struct.slabs()[..., :4] for backend in BACKENDS: with use_reflect_backend(backend) as abeles: assert_allclose(abeles(q, slabs), reflectivity, rtol=1e-14) # reverse the direction kf = kn(q, sld2, sld2) kb = kn(q, sld1, sld2) reflectance = (kf - kb) / (kf + kb) reflectivity = reflectance * np.conj(reflectance) # now from refnx code struct = SLD(sld2)(0, 0) | SLD(sld1)(0, 0) slabs = struct.slabs()[..., :4] for backend in BACKENDS: with use_reflect_backend(backend) as abeles: assert_allclose(abeles(q, slabs), reflectivity, rtol=1e-14)
def test_abeles_reshape(self, backend): # reflectivity should be able to deal with multidimensional input s = self.structure.slabs()[..., :4] reshaped_q = np.reshape(self.qvals, (2, 250)) reshaped_r = self.rvals.reshape(2, 250) with use_reflect_backend(backend) as abeles: calc = abeles(reshaped_q, s) assert_equal(calc.shape, reshaped_r.shape) assert_almost_equal(calc, reshaped_r, 15)
def test_noncontig_abeles(self, backend): # test for non-contiguous Q values tempq = self.qvals[0::5] slabs = self.structure.slabs()[..., :4] assert tempq.flags["C_CONTIGUOUS"] is False with use_reflect_backend(backend) as abeles: calc = abeles(tempq, slabs) assert_almost_equal(calc, self.rvals[0::5])
def resolution_test(slabs, data, backend): structure = Structure() for i, slab in enumerate(slabs): m = SLD(complex(slab[1], slab[2])) structure |= m(slab[0], slab[-1]) with use_reflect_backend(backend): model = ReflectModel(structure, bkg=0.0) model.quad_order = 17 R = model.model(data[:, 0], x_err=data[:, -1] * 2 * np.sqrt(2 * np.log(2))) np.testing.assert_allclose(R, data[:, 1], rtol=0.03)
def test_use_reflectivity_backend(self): import refnx.reflect._creflect as _creflect import refnx.reflect._reflect as _reflect reflect_model.abeles = _reflect.abeles with use_reflect_backend("c") as f: assert f == _creflect.abeles assert reflect_model.abeles == _creflect.abeles assert reflect_model.abeles == _reflect.abeles # this shouldn't error if pyopencl is not installed # it should just fall back to 'c' reflect_model.use_reflect_backend("pyopencl")
def test_abeles_absorption2(self, backend): # https://github.com/andyfaff/refl1d_analysis/tree/master/notebooks # this has an appreciable notch just below the critical edge refl1d = np.load(os.path.join(self.pth, "absorption.npy")) q = np.geomspace(0.005, 0.3, 201) depth = [0, 1200, 0] rho = [2.07, 4.66, 6.36] irho = [0, 0.016, 0] refnx_sigma = [np.nan, 10, 3] slabs = np.c_[depth, rho, irho, refnx_sigma] with use_reflect_backend(backend) as abeles: calc = abeles(q, slabs) assert_almost_equal(calc, refl1d[1])
def kernel_test(slabs, data, backend): """ Test the reflectivity kernels for refnx. Parameters ---------- slabs: np.ndarray Slab representation of the system data: np.ndarray Q, R arrays backend: {"c", "python", "cython", "pyopencl"} """ with use_reflect_backend(backend) as abeles: R = abeles(data[:, 0], slabs) assert R.shape == data[:, 1].shape np.testing.assert_allclose(R, data[:, 1], rtol=8e-5)
def test_parallel_calculator(self, backend): # test that parallel abeles work with a mapper q = np.linspace(0.01, 0.5, 1000).reshape(20, 50) p0 = np.array([ [0, 2.07, 0, 0], [100, 3.47, 0, 3], [500, -0.5, 1e-3, 3], [0, 6.36, 0, 3], ]) if backend == "pyopencl": # can't do pyopencl in a multiprocessing.Pool return with use_reflect_backend(backend) as abeles: wf = Wrapper_fn(abeles, p0) y = map(wf, q) with MapWrapper(2) as f: z = f(wf, q) assert_equal(z, np.array(list(y)))
def test_compare_refl1d(self, backend): # refl1d calculated with: # from refl1d import abeles # x = np.linspace(0.005, 0.5, 1001) # z = abeles.refl(x / 2, # [0, 100, 200, 0], # [2.07, 3.45, 5., 6.], # irho=[0.0, 0.1, 0.01, 0], # sigma=[3, 1, 5, 0]) # a = z.real ** 2 + z.imag ** 2 layers = np.array([ [0, 2.07, 0, 0], [100, 3.45, 0.1, 3], [200, 5.0, 0.01, 1], [0, 6.0, 0, 5], ]) x = np.linspace(0.005, 0.5, 1001) refl1d = np.load(os.path.join(self.pth, "refl1d.npy")) with use_reflect_backend(backend) as abeles: calc = abeles(x, layers) assert_almost_equal(calc, refl1d)