Пример #1
0
    def test_stepping_dim_in_condition_lowering(self):
        """
        Check that the compiler performs lowering on conditions
        with TimeDimensions and generates the expected code::

        if (g[t][x + 1][y + 1] <= 10){          if (g[t0][x + 1][y + 1] <= 10){
            ...                          -->       ...
        }                                       }

        This test increments a function by one at every timestep until it is
        less-or-equal to 10 (g<=10) while although operator runs for 13 timesteps.
        """
        grid = Grid(shape=(4, 4))
        _, y = grid.dimensions

        ths = 10
        g = TimeFunction(name='g', grid=grid)

        ci = ConditionalDimension(name='ci', parent=y, condition=Le(g, ths))

        op = Operator(Eq(g.forward, g + 1, implicit_dims=ci))

        op.apply(time_M=ths + 3)
        assert np.all(g.data[0, :, :] == ths)
        assert np.all(g.data[1, :, :] == ths + 1)
        assert 'if (g[t0][x + 1][y + 1] <= 10)\n'
        '{\n g[t1][x + 1][y + 1] = g[t0][x + 1][y + 1] + 1' in str(op.ccode)
Пример #2
0
    def test_expr_like_lowering(self):
        """
        Test the lowering of an expr-like ConditionalDimension's condition.
        This test makes an Operator that should indexify and lower the condition
        passed in the Conditional Dimension
        """

        grid = Grid(shape=(3, 3))
        g1 = Function(name='g1', grid=grid)
        g2 = Function(name='g2', grid=grid)

        g1.data[:] = 0.49
        g2.data[:] = 0.49
        x, y = grid.dimensions
        ci = ConditionalDimension(name='ci', parent=y, condition=Le((g1 + g2),
                                  1.01*(g1 + g2)))

        f = Function(name='f', shape=grid.shape, dimensions=(x, ci))
        Operator(Eq(f, g1+g2)).apply()

        assert np.all(f.data[:] == g1.data[:] + g2.data[:])
Пример #3
0
    def _axial_setup(self):
        """
        Update the axial distance function from the signed distance function.
        """
        # Recurring value for tidiness
        m_size = int(self._order/2)

        # Create a padded version of the signed distance function
        pad_sdf = Function(name='pad_sdf', grid=self._pad, space_order=self._order)
        pad_sdf.data[:] = np.pad(self._sdf.data, (m_size,), 'edge')

        # Set default values for axial distance
        self._axial[0].data[:] = -self._order*self._pad.spacing[0]
        self._axial[1].data[:] = -self._order*self._pad.spacing[1]
        self._axial[2].data[:] = -self._order*self._pad.spacing[2]

        # Equations to decompose distance into axial distances
        x, y, z = self._pad.dimensions
        h_x, h_y, h_z = self._pad.spacing
        pos = sp.Matrix([x*h_x, y*h_y, z*h_z])

        sdf_grad = grad(pad_sdf).evaluate  # Gradient of the sdf

        # Plane eq: a*x + b*y + c*z = d
        a = sdf_grad[0]
        b = sdf_grad[1]
        c = sdf_grad[2]
        d = sdf_grad.dot(pos - pad_sdf*sdf_grad)

        # Only need to calculate adjacent to boundary
        close_sdf = Le(sp.Abs(pad_sdf), h_x)

        # Conditional mask for calculation
        mask = ConditionalDimension(name='mask', parent=z,
                                    condition=close_sdf)

        eq_x = Eq(self._axial[0], (d - b*pos[1] - c*pos[2])/a - pos[0], implicit_dims=mask)
        eq_y = Eq(self._axial[1], (d - a*pos[0] - c*pos[2])/b - pos[1], implicit_dims=mask)
        eq_z = Eq(self._axial[2], (d - a*pos[0] - b*pos[1])/c - pos[2], implicit_dims=mask)

        op_axial = Operator([eq_x, eq_y, eq_z],
                            name='Axial')
        op_axial.apply()

        # Deal with silly values x
        x_nan_mask = np.isnan(self._axial[0].data)
        self._axial[0].data[x_nan_mask] = -self._order*h_x
        x_big_mask = np.abs(self._axial[0].data) > h_x
        self._axial[0].data[x_big_mask] = -self._order*h_x

        # Deal with silly values y
        y_nan_mask = np.isnan(self._axial[1].data)
        self._axial[1].data[y_nan_mask] = -self._order*h_y
        y_big_mask = np.abs(self._axial[1].data) > h_y
        self._axial[1].data[y_big_mask] = -self._order*h_y

        # Deal with silly values z
        z_nan_mask = np.isnan(self._axial[2].data)
        self._axial[2].data[z_nan_mask] = -self._order*h_z
        z_big_mask = np.abs(self._axial[2].data) > h_z
        self._axial[2].data[z_big_mask] = -self._order*h_z