Exemple #1
0
    def new_ops_arg(self, indexed, is_write):
        """
        Create an Indexed node using OPS representation.

        Parameters
        ----------
        indexed : Indexed
            Indexed object using devito representation.

        Returns
        -------
        Indexed
            Indexed node using OPS representation.
        """

        # Build the OPS arg identifier
        time_index = split_affine(indexed.indices[TimeFunction._time_position])
        ops_arg_id = ('%s%s%s' % (indexed.name, time_index.var, time_index.shift)
                      if indexed.function.is_TimeFunction else indexed.name)

        if ops_arg_id not in self.ops_args:
            symbol_to_access = OpsAccessible(
                ops_arg_id,
                dtype=indexed.dtype,
                read_only=not is_write
            )

            accessible_info = AccessibleInfo(
                symbol_to_access,
                time_index.var if indexed.function.is_TimeFunction else None,
                time_index.shift if indexed.function.is_TimeFunction else None,
                indexed.function.name)

            self.ops_args[ops_arg_id] = accessible_info
            self.ops_params.append(symbol_to_access)
        else:
            symbol_to_access = self.ops_args[ops_arg_id].accessible

        # Get the space indices
        space_indices = [
            split_affine(i).shift for i in indexed.indices
            if isinstance(split_affine(i).var, SpaceDimension)
        ]

        if space_indices not in self.ops_args_accesses[symbol_to_access]:
            self.ops_args_accesses[symbol_to_access].append(space_indices)

        return OpsAccess(symbol_to_access, space_indices)
Exemple #2
0
    def new_ops_arg(self, indexed):
        """
        Create an :class:`Indexed` node using OPS representation.

        Parameters
        ----------
        indexed : :class:`Indexed`
            Indexed object using devito representation.

        Returns
        -------
        :class:`Indexed`
            Indexed node using OPS representation.
        """

        # Build the OPS arg identifier
        time_index = split_affine(indexed.indices[TimeFunction._time_position])
        ops_arg_id = '%s%s%s' % (indexed.name, time_index.var,
                                 time_index.shift)

        if ops_arg_id not in self.ops_args:
            # Create the indexed object
            ops_arg = Array(name=ops_arg_id,
                            dimensions=[Dimension(name=namespace['ops_acc'])],
                            dtype=indexed.dtype)

            self.ops_args[ops_arg_id] = ops_arg
        else:
            ops_arg = self.ops_args[ops_arg_id]

        # Get the space indices
        space_indices = [
            e for i, e in enumerate(indexed.indices)
            if i != TimeFunction._time_position
        ]

        # Define the Macro used in OPS arg index
        access_macro = Macro(
            'OPS_ACC%d(%s)' % (list(self.ops_args).index(ops_arg_id), ','.join(
                str(split_affine(i).shift) for i in space_indices)))

        # Create Indexed object representing the OPS arg access
        new_indexed = Indexed(ops_arg.indexed, access_macro)

        return new_indexed
Exemple #3
0
    def new_ops_arg(self, indexed):
        """
        Create an :class:`Indexed` node using OPS representation.

        Parameters
        ----------
        indexed : :class:`Indexed`
            Indexed object using devito representation.

        Returns
        -------
        :class:`Indexed`
            Indexed node using OPS representation.
        """

        # Build the OPS arg identifier
        time_index = split_affine(indexed.indices[TimeFunction._time_position])
        ops_arg_id = '%s%s%s' % (indexed.name, time_index.var, time_index.shift)

        if ops_arg_id not in self.ops_args:
            # Create the indexed object
            ops_arg = Array(name=ops_arg_id,
                            dimensions=[Dimension(name=namespace['ops_acc'])],
                            dtype=indexed.dtype)

            self.ops_args[ops_arg_id] = ops_arg
        else:
            ops_arg = self.ops_args[ops_arg_id]

        # Get the space indices
        space_indices = [e for i, e in enumerate(
            indexed.indices) if i != TimeFunction._time_position]

        # Define the Macro used in OPS arg index
        access_macro = Macro('OPS_ACC%d(%s)' % (list(self.ops_args).index(ops_arg_id),
                                                ','.join(str(split_affine(i).shift)
                                                         for i in space_indices)))

        # Create Indexed object representing the OPS arg access
        new_indexed = Indexed(ops_arg.indexed, access_macro)

        return new_indexed
Exemple #4
0
 def handle_indexed(indexed):
     relation = []
     for i in indexed.indices:
         try:
             maybe_dim = split_affine(i).var
             if isinstance(maybe_dim, Dimension):
                 relation.append(maybe_dim)
         except ValueError:
             # Maybe there are some nested Indexeds (e.g., the situation is A[B[i]])
             nested = flatten(handle_indexed(n) for n in retrieve_indexed(i))
             if nested:
                 relation.extend(nested)
             else:
                 # Fallback: Just insert all the Dimensions we find, regardless of
                 # what the user is attempting to do
                 relation.extend([d for d in filter_sorted(i.free_symbols)
                                  if isinstance(d, Dimension)])
     return tuple(relation)
Exemple #5
0
 def handle_indexed(indexed):
     relation = []
     for i in indexed.indices:
         try:
             maybe_dim = split_affine(i).var
             if isinstance(maybe_dim, Dimension):
                 relation.append(maybe_dim)
         except ValueError:
             # Maybe there are some nested Indexeds (e.g., the situation is A[B[i]])
             nested = flatten(handle_indexed(n) for n in retrieve_indexed(i))
             if nested:
                 relation.extend(nested)
             else:
                 # Fallback: Just insert all the Dimensions we find, regardless of
                 # what the user is attempting to do
                 relation.extend([d for d in filter_sorted(i.free_symbols)
                                  if isinstance(d, Dimension)])
     return tuple(relation)
Exemple #6
0
def make_yask_ast(expr, yc_soln, mapper):

    def nary2binary(args, op):
        r = make_yask_ast(args[0], yc_soln, mapper)
        return r if len(args) == 1 else op(r, nary2binary(args[1:], op))

    if expr.is_Integer:
        return nfac.new_const_number_node(int(expr))
    elif expr.is_Float:
        return nfac.new_const_number_node(float(expr))
    elif expr.is_Rational:
        a, b = expr.as_numer_denom()
        return nfac.new_const_number_node(float(a)/float(b))
    elif expr.is_Symbol:
        function = expr.function
        if function.is_Constant:
            if function not in mapper:
                mapper[function] = yc_soln.new_grid(function.name, [])
            return mapper[function].new_grid_point([])
        elif function.is_Dimension:
            if expr.is_Time:
                return nfac.new_step_index(expr.name)
            elif expr.is_Space:
                return nfac.new_domain_index(expr.name)
            else:
                return nfac.new_misc_index(expr.name)
        else:
            # A DSE-generated temporary, which must have already been
            # encountered as a LHS of a previous expression
            assert function in mapper
            return mapper[function]
    elif expr.is_Indexed:
        # Create a YASK compiler grid if it's the first time we encounter a Function
        function = expr.function
        if function not in mapper:
            dimensions = [make_yask_ast(i, yc_soln, mapper) for i in function.indices]
            mapper[function] = yc_soln.new_grid(function.name, dimensions)
        # Convert the Indexed into a YASK grid access
        indices = []
        for i in expr.indices:
            if i.is_integer:
                # Typically, if we end up here it's because we have a misc dimension
                indices.append(make_yask_ast(i, yc_soln, mapper))
            else:
                # We must always use the parent ("main") dimension when creating
                # YASK expressions
                af = split_affine(i)
                dim = af.var.parent if af.var.is_Derived else af.var
                indices.append(make_yask_ast(dim + af.shift, yc_soln, mapper))
        return mapper[function].new_grid_point(indices)
    elif expr.is_Add:
        return nary2binary(expr.args, nfac.new_add_node)
    elif expr.is_Mul:
        return nary2binary(expr.args, nfac.new_multiply_node)
    elif expr.is_Pow:
        base, exp = expr.as_base_exp()
        if not exp.is_integer:
            raise NotImplementedError("Non-integer powers unsupported in "
                                      "Devito-YASK translation")

        if int(exp) < 0:
            num, den = expr.as_numer_denom()
            return nfac.new_divide_node(make_yask_ast(num, yc_soln, mapper),
                                        make_yask_ast(den, yc_soln, mapper))
        elif int(exp) >= 1:
            return nary2binary([base] * exp, nfac.new_multiply_node)
        else:
            warning("0-power found in Devito-YASK translation? setting to 1")
            return nfac.new_const_number_node(1)
    elif expr.is_Equality:
        if expr.lhs.is_Symbol:
            function = expr.lhs.base.function
            assert function not in mapper
            mapper[function] = make_yask_ast(expr.rhs, yc_soln, mapper)
        else:
            return nfac.new_equation_node(*[make_yask_ast(i, yc_soln, mapper)
                                            for i in expr.args])
    else:
        raise NotImplementedError("Missing handler in Devito-YASK translation")