def _check(self, shape):
     # check that both are im materials and store ims
     if not self._pre_solve_checks or shape != self._last_shape:
         if isinstance(self.model.surface_1.material, _IMMaterial) and \
            isinstance(self.model.surface_2.material, _IMMaterial):
             span = tuple([
                 s * (2 - pa) for s, pa in zip(shape, self._periodic_axes)
             ])
             im_1 = self.model.surface_1.material.influence_matrix(
                 [self.component], [self.model.surface_1.grid_spacing] * 2,
                 span)[self.component]
             im_2 = self.model.surface_2.material.influence_matrix(
                 [self.component], [self.model.surface_1.grid_spacing] * 2,
                 span)[self.component]
             self._im_1 = im_1
             self._im_2 = im_2
             self._im_total = im_1 + im_2
             self._pre_solve_checks = True
             self._base_conv_func = plan_convolve(np.zeros(shape),
                                                  self._im_total, None,
                                                  self._periodic_axes)
             self._last_shape = shape
         else:
             raise ValueError(
                 "This sub model only supports influence matrix based materials"
             )
def test_inverse_conv():
    np.random.seed(0)
    with slippy.OverRideCuda():
        loads = np.random.rand(128, 128)
        im = e_im('zz', loads.shape, (1e-6, 1e-6), 200e9, 0.3)
        conv_func = c.plan_convolve(loads, im, circular=True, fft_im=False)
        recovered = conv_func.inverse_conv(conv_func(loads), True)
        npt.assert_allclose(loads, recovered)
def test_raises_uequal_shapes_circ():
    with slippy.OverRideCuda():
        im = e_im('zz', (128, 128), (0.01, 0.01), 200e9, 0.3)
        load_shapes = [(128, 129), (128, 129), (129, 128), (129, 128)]
        circulars = [True, (False, True), True, (True, False)]
        for l_s, circ in zip(load_shapes, circulars):
            with npt.assert_raises(AssertionError):
                loads = np.zeros(l_s)
                _ = c.plan_convolve(loads, im, circular=circ)
Beispiel #4
0
 def contact_nodes(self, value):
     if value is None:
         self._contact_nodes = None
     else:
         value = np.array(value, dtype=bool)
         self._contact_nodes = value
     if self.im_mats:
         self.conv_func = plan_convolve(self._just_touching_gap,
                                        self.total_im,
                                        self._contact_nodes,
                                        circular=self._periodic_axes)
def test_non_circ_convolve_vs_scipy():
    with slippy.OverRideCuda():
        for l_s in loads_shapes:
            # generate an influence matrix, pick a component which is not symmetric!
            im_s = tuple(s * 2 for s in l_s)
            im = e_im('zx', im_s, (0.01, 0.01), 200e9, 0.3)
            loads = 1000 * np.random.rand(*l_s)
            scipy_result = fftconvolve(loads, im, mode='same')
            conv_func = c.plan_convolve(loads, im, fft_im=False)
            slippy_result = conv_func(loads)
            err_msg = f'Non circular convolution did not match scipy output for loads shape: {l_s} and IM shape: {im_s}'
            npt.assert_allclose(slippy_result, scipy_result, err_msg=err_msg)
Beispiel #6
0
def test_inverse_conv():
    np.random.seed(0)
    try:
        import cupy  # noqa: F401
        slippy.CUDA = True
    except ImportError:
        return
    loads = np.random.rand(128, 128)
    im = e_im('zz', loads.shape, (1e-6, 1e-6), 200e9, 0.3)
    conv_func = c.plan_convolve(loads, im, circular=True, fft_im=False)
    recovered = conv_func.inverse_conv(conv_func(loads), True)
    npt.assert_allclose(loads, cp.asnumpy(recovered))
def test_dont_raise_equal_shapes_circ():
    with slippy.OverRideCuda():
        im = e_im('zz', (128, 128), (0.01, 0.01), 200e9, 0.3)
        load_shapes = [(128, 128), (128, 64), (64, 64), (64, 128)]
        circulars = [True, (True, False), False, (False, True)]
        for l_s, circ in zip(load_shapes, circulars):
            loads = np.zeros(l_s)
            try:
                _ = c.plan_convolve(loads, im, circular=circ)
            except:  # noqa: E722
                raise AssertionError(
                    f"Plan convolve raised wrong error for mixed "
                    f"convolution load shape: {l_s}, circ: {circ}")
Beispiel #8
0
def test_raises_uequal_shapes_circ():
    try:
        import cupy  # noqa: F401
        slippy.CUDA = True
    except ImportError:
        return
    im = e_im('zz', (128, 128), (0.01, 0.01), 200e9, 0.3)
    load_shapes = [(128, 129), (128, 129), (129, 128), (129, 128)]
    circulars = [True, (False, True), True, (True, False)]
    for l_s, circ in zip(load_shapes, circulars):
        with npt.assert_raises(AssertionError):
            loads = np.zeros(l_s)
            _ = c.plan_convolve(loads, im, circular=circ)
def test_circ_convolve_location():
    with slippy.OverRideCuda():
        for im_s, l_s in zip(shapes_circ, shapes_circ):
            # generate an influence matrix, pick a component which is not symmetric!
            im = e_im('zz', im_s, (0.01, 0.01), 200e9, 0.3)
            loads = np.zeros(l_s)
            loads[64, 64] = 1000
            conv_func = c.plan_convolve(loads, im, circular=True)
            slippy_result = conv_func(loads)
            loc_load = np.argmax(loads)
            loc_result = np.argmax(slippy_result)
            err_msg = f'Circular convolution, location of load dosn\'t match displacement' \
                      f'for loads shape: {l_s} and IM shape: {im_s} \n ' \
                      f'expected: {np.unravel_index(loc_load,l_s)}, found: {np.unravel_index(loc_result,l_s)}'
            assert loc_load == loc_result, err_msg
def test_mixed_convolve():
    with slippy.OverRideCuda():
        for circ in [[True, False], [False, True]]:
            loads = np.zeros([128, 128])
            im_s = tuple((2 - p) * s for p, s in zip(circ, loads.shape))
            im = e_im('zz', im_s, (0.01, 0.01), 200e9, 0.3)
            loads[64, 64] = 1000
            conv_func = c.plan_convolve(loads, im, circular=circ)
            slippy_result = conv_func(loads)
            loc_load = np.argmax(loads)
            loc_result = np.argmax(slippy_result)
            err_msg = f'Mixed circular convolution, location of load dosn\'t match displacement' \
                      f'for circular: {circ} \n ' \
                      f'expected: {np.unravel_index(loc_load, loads.shape)}, ' \
                      f'found: {np.unravel_index(loc_result, loads.shape)}'
            assert loc_load == loc_result, err_msg
def test_vs_sequential():
    try:
        import cupy as cp
        slippy.CUDA = True
    except ImportError:
        return
    periodics = [(False, False), (True, False), (False, True), (True, True)]
    domains = (None, 0.5 > np.random.rand(16, 16))
    comps = ['xz', 'zz']
    loads = np.random.rand(16, 16)
    for p, d in itertools.product(periodics, domains):
        im_shape = tuple((2 - p) * s for p, s in zip(p, loads.shape))
        ims = np.array([
            core.elastic_influence_matrix_spatial(comp, im_shape, [1e-6] * 2,
                                                  200e9, 0.3) for comp in comps
        ])
        multi_func = core.plan_multi_convolve(loads, ims, d, p, fft_ims=False)
        if d is None:
            multi_result = multi_func(loads)
        else:
            multi_result = multi_func(loads[d])
        single_results = np.zeros_like(multi_result)
        single_funcs = []
        for i in range(2):
            single_func = core.plan_convolve(loads, ims[i], d, p, fft_im=False)
            if d is None:
                single_results[i] = single_func(loads)
            else:
                single_results[i] = single_func(loads[d])
            single_funcs.append(single_func)

        npt.assert_allclose(cp.asnumpy(multi_result),
                            cp.asnumpy(single_results),
                            atol=1e-30)

        if d is not None:
            multi_result = multi_func(loads[d], ignore_domain=True)
            single_results = np.zeros_like(multi_result)
            for i in range(2):
                single_results[i] = single_funcs[i](loads[d],
                                                    ignore_domain=True)

            npt.assert_allclose(cp.asnumpy(multi_result),
                                cp.asnumpy(single_results),
                                atol=1e-30)
Beispiel #12
0
def test_non_circ_convolve_location():
    try:
        import cupy as cp
        slippy.CUDA = True
    except ImportError:
        return
    for l_s in loads_shapes:
        # generate an influence matrix, pick a component which is not symmetric!
        im_s = tuple(s * 2 for s in l_s)
        im = e_im('zz', im_s, (0.01, 0.01), 200e9, 0.3)
        loads = np.zeros(l_s)
        loads[64, 64] = 1000
        conv_func = c.plan_convolve(loads, im)
        slippy_result = cp.asnumpy(conv_func(loads))
        loc_load = np.argmax(loads)
        loc_result = np.argmax(slippy_result)
        err_msg = f'Non circular convolution, location of load dosn\'t match displacement' \
                  f'for loads shape: {l_s} and IM shape: {im_s} \n ' \
                  f'expected: {np.unravel_index(loc_load,l_s)}, found: {np.unravel_index(loc_result,l_s)}'
        assert loc_load == loc_result, err_msg
Beispiel #13
0
    def results(self):
        if self._results is None:
            print("No results found in height opt func")
        if slippy.CUDA:
            xp = cp
        else:
            xp = np
        if self.im_mats and 'surface_1_displacement' not in self._results:
            # need to put the loads into an np array of right shape
            # find the full displacements (and convert to np array)
            # find disp on surface 1 and surface 2
            surf_1 = self._model.surface_1
            surf_2 = self._model.surface_2
            span = tuple([
                s * (2 - pa) for s, pa in zip(self._just_touching_gap.shape,
                                              self._periodic_axes)
            ])
            # noinspection PyUnresolvedReferences
            im1 = surf_1.material.influence_matrix(
                span=span,
                grid_spacing=[surf_1.grid_spacing] * 2,
                components=['zz'])['zz']
            # noinspection PyUnresolvedReferences
            im2 = surf_2.material.influence_matrix(
                span=span,
                grid_spacing=[surf_1.grid_spacing] * 2,
                components=['zz'])['zz']

            if 'domain' in self._results and 'loads_in_domain' in self._results:
                full_loads = xp.zeros(self._just_touching_gap.shape)
                full_loads[
                    self._results['domain']] = self._results['loads_in_domain']
                full_disp = slippy.asnumpy(
                    self.conv_func(self._results['loads_in_domain'],
                                   ignore_domain=True))
                full_loads = slippy.asnumpy(full_loads)

            elif 'loads_z' in self._results:
                full_loads = slippy.asnumpy(self._results['loads_z'])
                full_disp = slippy.asnumpy(
                    self._results['total_displacement_z'])
            else:
                raise ValueError("Results not properly set")

            conv_func_1 = plan_convolve(full_loads,
                                        im1,
                                        None,
                                        circular=self._periodic_axes)
            conv_func_2 = plan_convolve(full_loads,
                                        im2,
                                        None,
                                        circular=self._periodic_axes)

            disp_1 = conv_func_1(full_loads)
            disp_2 = conv_func_2(full_loads)

            if slippy.CUDA:
                disp_1, disp_2 = xp.asnumpy(disp_1), xp.asnumpy(disp_2)
                full_loads = xp.asnumpy(full_loads)

            total_load = float(np.sum(full_loads) * self._grid_spacing**2)

            if 'contact_nodes' in self._results:
                contact_nodes = self._results['contact_nodes']
            else:
                contact_nodes = full_loads > 0

            if 'gap' in self._results:
                gap = self._results['gap']
            else:
                gap = self._just_touching_gap - self._results[
                    'interference'] + full_disp

            results = {
                'loads_z': full_loads,
                'total_displacement_z': full_disp,
                'surface_1_displacement_z': disp_1,
                'surface_2_displacement_z': disp_2,
                'contact_nodes': contact_nodes,
                'total_normal_load': total_load,
                'interference': self._results['interference'],
                'gap': gap
            }
            return results
        else:
            return self._results