Пример #1
0
    def field(cls,
              members,
              shape=None,
              name="<Struct>",
              offset=None,
              needs_grad=False,
              layout=Layout.AOS):

        if shape is None and offset is not None:
            raise TaichiSyntaxError(
                "shape cannot be None when offset is being set")

        field_dict = {}

        for key, dtype in members.items():
            field_name = name + '.' + key
            if isinstance(dtype, CompoundType):
                field_dict[key] = dtype.field(shape=None,
                                              name=field_name,
                                              offset=offset,
                                              needs_grad=needs_grad)
            else:
                field_dict[key] = impl.field(dtype,
                                             shape=None,
                                             name=field_name,
                                             offset=offset,
                                             needs_grad=needs_grad)

        if shape is not None:
            if isinstance(shape, numbers.Number):
                shape = (shape, )
            if isinstance(offset, numbers.Number):
                offset = (offset, )

            if offset is not None and len(shape) != len(offset):
                raise TaichiSyntaxError(
                    f'The dimensionality of shape and offset must be the same ({len(shape)} != {len(offset)})'
                )
            dim = len(shape)
            if layout == Layout.SOA:
                for e in field_dict.values():
                    ti.root.dense(impl.index_nd(dim),
                                  shape).place(e, offset=offset)
                if needs_grad:
                    for e in field_dict.values():
                        ti.root.dense(impl.index_nd(dim),
                                      shape).place(e.grad, offset=offset)
            else:
                ti.root.dense(impl.index_nd(dim),
                              shape).place(*tuple(field_dict.values()),
                                           offset=offset)
                if needs_grad:
                    grads = tuple(e.grad for e in field_dict.values())
                    ti.root.dense(impl.index_nd(dim),
                                  shape).place(*grads, offset=offset)
        return StructField(field_dict, name=name)
Пример #2
0
def allocate_dual(x, dual_root):
    """Allocate dual field for forward mode autodiff
    """
    dtype = x.dtype
    shape = x.shape
    dim = len(shape)
    x_dual = impl.field(dtype)
    x._set_grad(x_dual, reverse_mode=False)
    x._get_field_members()[0].ptr.set_dual(x_dual._get_field_members()[0].ptr)
    dual_root.dense(impl.index_nd(dim), shape).place(x_dual)
Пример #3
0
    def field(cls,
              members,
              shape=None,
              name="<Struct>",
              offset=None,
              needs_grad=False,
              layout=Layout.AOS):
        """Creates a :class:`~taichi.StructField` with each element
        has this struct as its type.

        Args:
            members (dict): a dict, each item is like `name: type`.
            shape (Tuple[int]): width and height of the field.
            offset (Tuple[int]): offset of the indices of the created field.
                For example if `offset=(-10, -10)` the indices of the field
                will start at `(-10, -10)`, not `(0, 0)`.
            needs_grad (bool): enabling gradient field or not.
            layout: AOS or SOA.

        Example:

            >>> vec3 = ti.types.vector(3, ti.f32)
            >>> sphere = {"center": vec3, "radius": float}
            >>> F = ti.Struct.field(sphere, shape=(3, 3))
            >>> F
            {'center': array([[[0., 0., 0.],
                [0., 0., 0.],
                [0., 0., 0.]],

               [[0., 0., 0.],
                [0., 0., 0.],
                [0., 0., 0.]],

               [[0., 0., 0.],
                [0., 0., 0.],
                [0., 0., 0.]]], dtype=float32), 'radius': array([[0., 0., 0.],
               [0., 0., 0.],
               [0., 0., 0.]], dtype=float32)}
        """

        if shape is None and offset is not None:
            raise TaichiSyntaxError(
                "shape cannot be None when offset is being set")

        field_dict = {}

        for key, dtype in members.items():
            field_name = name + '.' + key
            if isinstance(dtype, CompoundType):
                field_dict[key] = dtype.field(shape=None,
                                              name=field_name,
                                              offset=offset,
                                              needs_grad=needs_grad)
            else:
                field_dict[key] = impl.field(dtype,
                                             shape=None,
                                             name=field_name,
                                             offset=offset,
                                             needs_grad=needs_grad)

        if shape is not None:
            if isinstance(shape, numbers.Number):
                shape = (shape, )
            if isinstance(offset, numbers.Number):
                offset = (offset, )

            if offset is not None and len(shape) != len(offset):
                raise TaichiSyntaxError(
                    f'The dimensionality of shape and offset must be the same ({len(shape)} != {len(offset)})'
                )
            dim = len(shape)
            if layout == Layout.SOA:
                for e in field_dict.values():
                    impl.root.dense(impl.index_nd(dim),
                                    shape).place(e, offset=offset)
                if needs_grad:
                    for e in field_dict.values():
                        impl.root.dense(impl.index_nd(dim),
                                        shape).place(e.grad, offset=offset)
            else:
                impl.root.dense(impl.index_nd(dim),
                                shape).place(*tuple(field_dict.values()),
                                             offset=offset)
                if needs_grad:
                    grads = tuple(e.grad for e in field_dict.values())
                    impl.root.dense(impl.index_nd(dim),
                                    shape).place(*grads, offset=offset)
        return StructField(field_dict, name=name)
Пример #4
0
    def field(cls,
              n,
              m,
              dtype,
              shape=None,
              name="",
              offset=None,
              needs_grad=False,
              layout=None):  # TODO(archibate): deprecate layout
        '''ti.Matrix.field'''
        self = cls.empty(n, m)
        self.entries = []
        self.n = n
        self.m = m
        self.dt = dtype

        if isinstance(dtype, (list, tuple, np.ndarray)):
            # set different dtype for each element in Matrix
            # see #2135
            if m == 1:
                assert len(np.shape(dtype)) == 1 and len(
                    dtype
                ) == n, f'Please set correct dtype list for Vector. The shape of dtype list should be ({n}, ) instead of {np.shape(dtype)}'
                for i in range(n):
                    self.entries.append(impl.field(dtype[i], name=name))
            else:
                assert len(np.shape(dtype)) == 2 and len(dtype) == n and len(
                    dtype[0]
                ) == m, f'Please set correct dtype list for Matrix. The shape of dtype list should be ({n}, {m}) instead of {np.shape(dtype)}'
                for i in range(n):
                    for j in range(m):
                        self.entries.append(impl.field(dtype[i][j], name=name))
        else:
            for _ in range(n * m):
                self.entries.append(impl.field(dtype, name=name))
        self.grad = self.make_grad()

        if layout is not None:
            assert shape is not None, 'layout is useless without shape'
        if shape is None:
            assert offset is None, "shape cannot be None when offset is being set"

        if shape is not None:
            if isinstance(shape, numbers.Number):
                shape = (shape, )
            if isinstance(offset, numbers.Number):
                offset = (offset, )

            if offset is not None:
                assert len(shape) == len(
                    offset
                ), f'The dimensionality of shape and offset must be the same  ({len(shape)} != {len(offset)})'

            if layout is None:
                layout = ti.AOS

            dim = len(shape)
            if layout.soa:
                for i, e in enumerate(self.entries):
                    ti.root.dense(impl.index_nd(dim),
                                  shape).place(e, offset=offset)
                if needs_grad:
                    for i, e in enumerate(self.entries):
                        ti.root.dense(impl.index_nd(dim),
                                      shape).place(e.grad, offset=offset)
            else:
                var_list = []
                for i, e in enumerate(self.entries):
                    var_list.append(e)
                ti.root.dense(impl.index_nd(dim),
                              shape).place(*tuple(var_list), offset=offset)
                grad_var_list = []
                if needs_grad:
                    for i, e in enumerate(self.entries):
                        grad_var_list.append(e.grad)
                    ti.root.dense(impl.index_nd(dim),
                                  shape).place(*tuple(grad_var_list),
                                               offset=offset)
        return self
Пример #5
0
    def field(cls,
              n,
              m,
              dtype,
              shape=None,
              name="",
              offset=None,
              needs_grad=False,
              layout=None):  # TODO(archibate): deprecate layout
        """Construct a data container to hold all elements of the Matrix.

        Args:
            n (int): The desired number of rows of the Matrix.
            m (int): The desired number of columns of the Matrix.
            dtype (DataType, optional): The desired data type of the Matrix.
            shape (Union[int, tuple of int], optional): The desired shape of the Matrix.
            name (string, optional): The custom name of the field.
            offset (Union[int, tuple of int], optional): The coordinate offset of all elements in a field.
            needs_grad (bool, optional): Whether the Matrix need gradients.
            layout (:class:`~taichi.lang.impl.Layout`, optional): The field layout, i.e., Array Of Structure(AOS) or Structure Of Array(SOA).

        Returns:
            :class:`~taichi.lang.matrix.Matrix`: A :class:`~taichi.lang.matrix.Matrix` instance serves as the data container.

        """
        self = cls.empty(n, m)
        self.entries = []
        self.n = n
        self.m = m
        self.dt = dtype

        if isinstance(dtype, (list, tuple, np.ndarray)):
            # set different dtype for each element in Matrix
            # see #2135
            if m == 1:
                assert len(np.shape(dtype)) == 1 and len(
                    dtype
                ) == n, f'Please set correct dtype list for Vector. The shape of dtype list should be ({n}, ) instead of {np.shape(dtype)}'
                for i in range(n):
                    self.entries.append(impl.field(dtype[i], name=name))
            else:
                assert len(np.shape(dtype)) == 2 and len(dtype) == n and len(
                    dtype[0]
                ) == m, f'Please set correct dtype list for Matrix. The shape of dtype list should be ({n}, {m}) instead of {np.shape(dtype)}'
                for i in range(n):
                    for j in range(m):
                        self.entries.append(impl.field(dtype[i][j], name=name))
        else:
            for _ in range(n * m):
                self.entries.append(impl.field(dtype, name=name))
        self.grad = self.make_grad()

        if layout is not None:
            assert shape is not None, 'layout is useless without shape'
        if shape is None:
            assert offset is None, "shape cannot be None when offset is being set"

        if shape is not None:
            if isinstance(shape, numbers.Number):
                shape = (shape, )
            if isinstance(offset, numbers.Number):
                offset = (offset, )

            if offset is not None:
                assert len(shape) == len(
                    offset
                ), f'The dimensionality of shape and offset must be the same  ({len(shape)} != {len(offset)})'

            if layout is None:
                layout = ti.AOS

            dim = len(shape)
            if layout.soa:
                for i, e in enumerate(self.entries):
                    ti.root.dense(impl.index_nd(dim),
                                  shape).place(e, offset=offset)
                if needs_grad:
                    for i, e in enumerate(self.entries):
                        ti.root.dense(impl.index_nd(dim),
                                      shape).place(e.grad, offset=offset)
            else:
                var_list = []
                for i, e in enumerate(self.entries):
                    var_list.append(e)
                ti.root.dense(impl.index_nd(dim),
                              shape).place(*tuple(var_list), offset=offset)
                grad_var_list = []
                if needs_grad:
                    for i, e in enumerate(self.entries):
                        grad_var_list.append(e.grad)
                    ti.root.dense(impl.index_nd(dim),
                                  shape).place(*tuple(grad_var_list),
                                               offset=offset)
        return self
Пример #6
0
    def field(cls,
              n,
              m,
              dtype,
              shape=None,
              name="",
              offset=None,
              needs_grad=False,
              layout=Layout.AOS):
        """Construct a data container to hold all elements of the Matrix.

        Args:
            n (int): The desired number of rows of the Matrix.
            m (int): The desired number of columns of the Matrix.
            dtype (DataType, optional): The desired data type of the Matrix.
            shape (Union[int, tuple of int], optional): The desired shape of the Matrix.
            name (string, optional): The custom name of the field.
            offset (Union[int, tuple of int], optional): The coordinate offset of all elements in a field.
            needs_grad (bool, optional): Whether the Matrix need gradients.
            layout (Layout, optional): The field layout, i.e., Array Of Structure (AOS) or Structure Of Array (SOA).

        Returns:
            :class:`~taichi.lang.matrix.Matrix`: A :class:`~taichi.lang.matrix.Matrix` instance serves as the data container.

        """
        entries = []
        if isinstance(dtype, (list, tuple, np.ndarray)):
            # set different dtype for each element in Matrix
            # see #2135
            if m == 1:
                assert len(np.shape(dtype)) == 1 and len(
                    dtype
                ) == n, f'Please set correct dtype list for Vector. The shape of dtype list should be ({n}, ) instead of {np.shape(dtype)}'
                for i in range(n):
                    entries.append(
                        impl.create_field_member(dtype[i], name=name))
            else:
                assert len(np.shape(dtype)) == 2 and len(dtype) == n and len(
                    dtype[0]
                ) == m, f'Please set correct dtype list for Matrix. The shape of dtype list should be ({n}, {m}) instead of {np.shape(dtype)}'
                for i in range(n):
                    for j in range(m):
                        entries.append(
                            impl.create_field_member(dtype[i][j], name=name))
        else:
            for _ in range(n * m):
                entries.append(impl.create_field_member(dtype, name=name))
        entries, entries_grad = zip(*entries)
        entries, entries_grad = MatrixField(entries, n, m), MatrixField(
            entries_grad, n, m)
        entries.set_grad(entries_grad)

        if shape is None:
            assert offset is None, "shape cannot be None when offset is being set"

        if shape is not None:
            if isinstance(shape, numbers.Number):
                shape = (shape, )
            if isinstance(offset, numbers.Number):
                offset = (offset, )

            if offset is not None:
                assert len(shape) == len(
                    offset
                ), f'The dimensionality of shape and offset must be the same  ({len(shape)} != {len(offset)})'

            dim = len(shape)
            if layout == Layout.SOA:
                for e in entries.get_field_members():
                    ti.root.dense(impl.index_nd(dim),
                                  shape).place(ScalarField(e), offset=offset)
                if needs_grad:
                    for e in entries_grad.get_field_members():
                        ti.root.dense(impl.index_nd(dim),
                                      shape).place(ScalarField(e),
                                                   offset=offset)
            else:
                ti.root.dense(impl.index_nd(dim), shape).place(entries,
                                                               offset=offset)
                if needs_grad:
                    ti.root.dense(impl.index_nd(dim),
                                  shape).place(entries_grad, offset=offset)
        return entries