Source code for psyclone.domain.lfric.lfric_builtins

# -----------------------------------------------------------------------------
# BSD 3-Clause License
#
# Copyright (c) 2017-2026, Science and Technology Facilities Council.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
#   list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
#   this list of conditions and the following disclaimer in the documentation
#   and/or other materials provided with the distribution.
#
# * Neither the name of the copyright holder nor the names of its
#   contributors may be used to endorse or promote products derived from
#   this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# -----------------------------------------------------------------------------
# Author A. R. Porter, STFC Daresbury Lab
# Modified by I. Kavcic, L. Turner and O. Brunt, Met Office
# Modified by J. Henrichs, Bureau of Meteorology
# Modified by R. W. Ford, N. Nobre and S. Siso, STFC Daresbury Lab

''' This module implements the support for 'built-in' operations in the
    PSyclone LFRic API. Each supported built-in is implemented
    as a different Python class, all inheriting from the LFRicBuiltIn class.
    The LFRicBuiltInCallFactory creates the Python object required for
    a given built-in call. '''

# pylint: disable=too-many-lines
import abc
from enum import Enum, auto

from psyclone.configuration import Config
from psyclone.core import AccessType, Signature, VariablesAccessMap
from psyclone.domain.lfric import LFRicConstants
from psyclone.domain.lfric.kernel import (
    LFRicKernelMetadata, FieldArgMetadata, ScalarArgMetadata,
    FieldVectorArgMetadata)
from psyclone.domain.lfric.lfric_types import LFRicTypes
from psyclone.errors import GenerationError, InternalError
from psyclone.parse.utils import ParseError
from psyclone.psyGen import BuiltIn
from psyclone.psyir.nodes import (ArrayReference, Assignment, BinaryOperation,
                                  Reference, IntrinsicCall)
from psyclone.psyir.nodes.node import Node
from psyclone.psyir.symbols import DataSymbol, UnsupportedFortranType
from psyclone.utils import a_or_an

#: The name of the file containing the meta-data describing the
#: built-in operations for this API
BUILTIN_DEFINITIONS_FILE = "lfric_builtins_mod.f90"


# Function to return the built-in operations that we support for this API.
# The meta-data describing these kernels is in lfric_builtins_mod.f90.
# The built-in operations F90 capitalised names are dictionary keys and need
# to be converted to lower case for invoke-generation purpose.
def get_lowercase_builtin_map(builtin_map_capitalised_dict):
    '''
    Convert the names of the supported built-in operations to lowercase
    for comparison and invoke-generation purpose.

    :param builtin_map_capitalised_dict: a dictionary of built-in names.
    :type builtin_map_capitalised_dict: dict of str

    :returns: a dictionary of lowercase Fortran built-in names as keys
              and case-sensitive Python built-in names as values.
    :rtype: dict of str

    '''
    builtin_map_dict = {}
    for fortran_name in builtin_map_capitalised_dict:
        python_name = builtin_map_capitalised_dict[fortran_name]
        builtin_map_dict[fortran_name.lower()] = python_name
    return builtin_map_dict


[docs] class LFRicBuiltInCallFactory(): '''Creates the necessary framework for a call to an LFRic built-in, This consists of the operation itself and the loop over unique DoFs. ''' def __str__(self): return "Factory for a call to an LFRic built-in."
[docs] @staticmethod def create(call, parent=None): ''' Create the objects needed for a call to the built-in described in the call (BuiltInCall) object. :param call: details of the call to this built-in in the \ Algorithm layer. :type call: :py:class:`psyclone.parse.algorithm.BuiltInCall` :param parent: the schedule instance to which the built-in call \ belongs. :type parent: :py:class:`psyclone.domain.lfric.LFRicInvokeSchedule` :raises ParseError: if the name of the function being called is \ not a recognised built-in. :raises InternalError: if the built-in does not iterate over DoFs. ''' if call.func_name not in BUILTIN_MAP: raise ParseError( f"Unrecognised built-in call in LFRic API: found " f"'{call.func_name}' but expected one of " f"{list(BUILTIN_MAP_CAPITALISED.keys())}.") # Use our dictionary to get the correct Python object for # this built-in. builtin = BUILTIN_MAP[call.func_name]() # Create the loop over the appropriate entity. if (call.ktype.iterates_over in LFRicConstants().DOF_ITERATION_SPACES): loop_type = "dof" else: raise InternalError( f"An LFRic built-in must iterate over one of " f"{LFRicConstants().DOF_ITERATION_SPACES} but kernel " f"'{call.func_name}' iterates over " f"'{call.ktype.iterates_over}'") # Avoid circular import # pylint: disable=import-outside-toplevel from psyclone.domain.lfric import LFRicLoop dofloop = LFRicLoop(parent=parent, loop_type=loop_type) # Use the call object (created by the parser) to set-up the state # of the infrastructure kernel builtin.load(call, parent=dofloop.loop_body) # Set-up its state dofloop.load(builtin) # As it is the innermost loop it has the kernel as a loop_body # child. dofloop.loop_body.addchild(builtin) # Return the outermost loop return dofloop
[docs] class LFRicBuiltIn(BuiltIn, metaclass=abc.ABCMeta): '''Abstract base class for a node representing a call to an LFRic built-in. :raises NotImplementedError: if a subclass of this abstract class does not set the value of '_datatype'. '''
[docs] class ReductionType(Enum): ''' Enumeration of the types of reduction an LFRicBuiltIn can perform. ''' #: No reduction. NONE = auto() #: Summation reduction. SUM = auto() #: Global minimum value. MIN = auto() #: Global maximum value. MAX = auto()
_case_name = None _datatype = None #: The type of reduction performed by this kernel. _reduction_type: ReductionType = ReductionType.NONE def __init__(self): # Builtins do not accept quadrature self.qr_rules = {} # Builtins cannot request mesh properties self.mesh = None self._idx_name = None if not self._datatype: raise NotImplementedError( "An LFRicBuiltIn should be overridden by a subclass that " "sets the value of '_datatype', but '_datatype' is not set.") super().__init__()
[docs] @staticmethod @abc.abstractmethod def metadata(): '''Must be overridden by subclass.'''
@classmethod def _builtin_metadata(cls, meta_args): '''Utility to take 'meta_args' metadata and return LFRic kernel metadata for a built-in. Assumes the metadata describes a built-in kernel that operates on a DoF and that the naming protocol uses the name of the metadata type and adds '_code' to it for the name of the subroutine. :param meta_args: a list of 'meta_args' metadata. :type meta_args: List[subclass of \ :py:class:`psyclone.domain.lfric.kernel.CommonArgMetadata`] :returns: LFRic kernel metadata for this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' return LFRicKernelMetadata( meta_args=meta_args, operates_on="dof", procedure_name=f"{cls._case_name}_code", name=cls._case_name) def __str__(self): metadata = self.metadata() plural = "" # Builtins are currently limited to fields and scalars but add # in a check for field-vectors as well for future proofing. if len(metadata.meta_args_get([ FieldArgMetadata, FieldVectorArgMetadata])) > 1: plural = "s" return (f"Built-in: {self._case_name} (" f"{self._datatype}-valued field{plural})")
[docs] def reference_accesses(self) -> VariablesAccessMap: ''' :returns: a map of all the symbol accessed inside this node, the keys are Signatures (unique identifiers to a symbol and its structure accessors) and the values are AccessSequence (a sequence of AccessTypes). :raises InternalError: if an unsupported argument type is encountered. ''' var_accesses = VariablesAccessMap() table = self.scope.symbol_table # Collect all write access in a separate object, so they can be added # after all read access (which must happen before something is written) written = VariablesAccessMap() suffix_map = LFRicConstants().ARG_TYPE_SUFFIX_MAPPING for arg in self.args: if arg.form in ["variable", "indexed_variable"]: if arg.is_field: sym = table.lookup_with_tag( f"{arg.name}:{suffix_map[arg.argument_type]}") name = sym.name elif arg.is_scalar: name = arg.declaration_name else: raise InternalError( f"LFRicBuiltin.reference_accesses only supports field " f"and scalar arguments but got '{arg.name}' of type " f"'{arg.argument_type}'") if arg.access == AccessType.WRITE: written.add_access(Signature(name), arg.access, self) else: var_accesses.add_access(Signature(name), arg.access, self) # Now merge the write access to the end of all other accesses: var_accesses.update(written) return var_accesses
[docs] def load(self, call, parent=None): ''' Populate the state of this object using the supplied call object. :param call: The BuiltIn object from which to extract information \ about this built-in call. :type call: :py:class:`psyclone.parse.algorithm.BuiltInCall` :param parent: The parent node of the kernel call in the PSyIR \ we are constructing. This will be a loop. :type parent: :py:class:`psyclone.domain.lfric.LFRicLoop` ''' # Avoid circular import # pylint: disable=import-outside-toplevel from psyclone.lfric import FSDescriptors, LFRicKernelArguments BuiltIn.load(self, call, LFRicKernelArguments, parent) self.arg_descriptors = call.ktype.arg_descriptors self._func_descriptors = call.ktype.func_descriptors self._fs_descriptors = FSDescriptors(call.ktype.func_descriptors) self._idx_name = self.get_dof_loop_index_symbol().name # Check that this built-in kernel is valid self._validate()
def _validate(self): ''' Check that this built-in conforms to the LFRic API. :raises ParseError: if a built-in call does not iterate over DoFs. :raises ParseError: if an argument to a built-in kernel is not one of valid argument types. :raises ParseError: if an argument to a built-in kernel has an invalid data type. :raises ParseError: if a built-in kernel writes to more than one argument. :raises ParseError: if a built-in kernel does not have at least one field argument. :raises ParseError: if all field arguments are not on the same space. :raises ParseError: if all field arguments of a non-conversion built-in do not have the same data type. :raises GenerationError: if this kernel does not support redundant computation and COMPUTE_ANNEXED_DOFS is True. ''' const = LFRicConstants() # Check that our assumption that we're looping over DoFs is valid if self.iterates_over not in const.DOF_ITERATION_SPACES: raise ParseError( f"In the LFRic API built-in calls must operate on one of " f"{const.DOF_ITERATION_SPACES} but found " f"'{self.iterates_over}' for {self}.") # Check write count, field arguments and spaces write_count = 0 # Only one argument must be written to field_count = 0 # We must have one or more fields as arguments spaces = set() # All field arguments must be on the same space # Built-ins update fields DoF by DoF and therefore can have # WRITE/READWRITE access write_access_modes = [AccessType.REDUCTION, AccessType.WRITE, AccessType.READWRITE] # Field data types must be the same except for the conversion built-ins data_types = set() for arg in self.arg_descriptors: # Check valid argument types if arg.argument_type not in const.VALID_BUILTIN_ARG_TYPES: raise ParseError( f"In the LFRic API an argument to a built-in kernel " f"must be one of {const.VALID_BUILTIN_ARG_TYPES} but " f"kernel '{self.name}' has an argument of type " f"'{arg.argument_type}'.") # Check valid data types if arg.data_type not in const.VALID_BUILTIN_DATA_TYPES: raise ParseError( f"In the LFRic API an argument to a built-in kernel " f"must have one of {const.VALID_BUILTIN_DATA_TYPES} as " f"a data type but kernel '{self.name}' has an argument " f"of data type '{arg.data_type}'.") # Check for write accesses if arg.access in write_access_modes: write_count += 1 if arg.argument_type in const.VALID_FIELD_NAMES: field_count += 1 spaces.add(arg.function_space) data_types.add(arg.data_type) if write_count != 1: raise ParseError(f"A built-in kernel in the LFRic API must " f"have one and only one argument that is " f"written to but found {write_count} for " f"kernel '{self.name}'.") if field_count == 0: raise ParseError(f"A built-in kernel in the LFRic API must have " f"at least one field as an argument but " f"kernel '{self.name}' has none.") if len(spaces) != 1: spaces_str = [str(x) for x in sorted(spaces)] raise ParseError( f"All field arguments to a built-in in the LFRic API " f"must be on the same space. However, found spaces " f"{spaces_str} for arguments to '{self.name}'") conversion_builtins = ["real_to_int_X", "real_to_real_X", "int_to_real_X"] conversion_builtins_lower = [x.lower() for x in conversion_builtins] if len(data_types) != 1 and self.name not in conversion_builtins_lower: data_types_str = [str(x) for x in sorted(data_types)] raise ParseError( f"In the LFRic API only the data type conversion built-ins " f"{conversion_builtins} are allowed to have field arguments of" f" different data types. However, found different data types " f"{data_types_str} for field arguments to '{self.name}'.") api_config = Config.get().api_conf("lfric") if (api_config.compute_annexed_dofs and self.iterates_over in const.NO_RC_ITERATION_SPACES): raise GenerationError( f"Built-in '{self.name}' cannot perform redundant computation " f"(has OPERATES_ON={self.iterates_over}) but the 'COMPUTE_" f"ANNEXED_DOFS' configuration option is set to True.") @property def halo_depth(self): ''' :returns: None as BuiltIns do not (by default) iterate into halo cells. :rtype: NoneType ''' return None @property def undf_name(self): ''' Dynamically looks up the name of the 'undf' variable for the space that this kernel updates. :returns: the name of the undf variable. :rtype: str ''' field = self._arguments.iteration_space_arg() return field.function_space.undf_name @property def qr_required(self): ''' Built-ins do not currently require quadrature. :returns: False :rtype: bool ''' return False @property def reference_element(self): ''' Built-ins do not require reference-element properties. :returns: None :rtype: NoneType ''' return None @property def cma_operation(self): ''' Built-ins do not perform operations with Column-Matrix-Assembly operators. :returns: None :rtype: NoneType ''' return None @property def is_intergrid(self): ''' We don't have any inter-grid built-ins. :returns: False :rtype: bool ''' return False @property def fs_descriptors(self): ''' :returns: a list of function space descriptor objects which \ contain information about the function spaces. :rtype: list of :py:class:`psyclone.lfric.FSDescriptor` ''' return self._fs_descriptors @property def reduction_type(self) -> ReductionType: ''' :returns: the type of reduction operation performed by this Built-in. ''' return self._reduction_type
[docs] def get_dof_loop_index_symbol(self) -> DataSymbol: ''' Finds or creates the symbol representing the index in any loops over DoFs. :returns: symbol representing the DoF loop index. ''' table = self.scope.symbol_table # The symbol representing the loop index is created in the LFRicLoop # constructor. return table.find_or_create( "df", tag="dof_loop_idx", symbol_type=DataSymbol, datatype=LFRicTypes("LFRicIntegerScalarDataType")())
[docs] def get_indexed_field_argument_references(self): ''' Creates a DoF-indexed StructureReference for each of the field arguments to this Built-In kernel. e.g. if the kernel has a field argument named 'fld1' then this routine will create an ArrayReference for 'fld1_data(df)' where 'df' is the DoF-loop variable and 'fld1_data' is the pointer to the data array within the fld1 object. :returns: a reference to the 'df'th element of each kernel argument that is a field. :rtype: List[:py:class:`psyclone.psyir.nodes.ArrayReference`] ''' table = self.scope.symbol_table idx_sym = self.get_dof_loop_index_symbol() suffixes = LFRicConstants().ARG_TYPE_SUFFIX_MAPPING refs = [] for arg in self._arguments.args: if not arg.is_field: continue sym = table.lookup_with_tag( f"{arg.name}:{suffixes[arg.argument_type]}") refs.append(ArrayReference.create(sym, [Reference(idx_sym)])) return refs
[docs] def get_scalar_argument_references(self): ''' Finds or creates either a Reference (for a symbol) or PSyIR (for a literal expression) for any scalar arguments to this Built-In kernel. :returns: a Reference or PSyIR expression for each scalar kernel argument. :rtype: list of subclasses of `:py:class:`psyclone.psyir.nodes.Node` ''' return [arg.psyir_expression() for arg in self._arguments.args if arg.is_scalar]
def _replace_with_assignment(self, lhs, rhs): ''' Creates an assignment from the left- and right-hand-side nodes, then replaces this Builtin with the newly-created Assignment node. :param lhs: The left-hand side of the assignment to be created. :type lhs: :py:class:`psyclone.psyir.nodes.ArrayReference` :param rhs: The right-hand side of the assignment to be created. :type rhs: :py:class:`psyclone.psyir.nodes.DataNode` :returns: the new Assignment node. :rtype: :py:class:`psyclone.psyir.nodes.Assignment` ''' assign = Assignment.create(lhs, rhs) # Add a preceding comment to the Assignment assign.preceding_comment = str(self) self.replace_with(assign) return assign
# ******************************************************************* # # ************** Built-ins for real-valued fields ******************* # # ******************************************************************* # # ------------------------------------------------------------------- # # ============== Adding (scaled) real fields ======================== # # ------------------------------------------------------------------- #
[docs] class LFRicXPlusYKern(LFRicBuiltIn): ''' Add one, real-valued, field to another and return the result as a third, real-valued, field. ''' _case_name = "X_plus_Y" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. Implemented in a datatype-independent way to allow for re-use. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] metadata = cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")]) metadata.validate() return metadata
def __str__(self): return (f"Built-in: {self._case_name} (add " f"{self._datatype}-valued fields)")
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This Built-In node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = proxy1%data(df) + proxy2%data(df) lhs = arg_refs[0] rhs = BinaryOperation.create(BinaryOperation.Operator.ADD, arg_refs[1], arg_refs[2]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicIncXPlusYKern(LFRicBuiltIn): ''' Add the second, real-valued, field to the first field and return it. ''' _case_name = "inc_X_plus_Y" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
def __str__(self): return (f"Built-in: {self._case_name} (increment " f"{a_or_an(self._datatype)} {self._datatype}-valued field)")
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed refs for both of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = proxy0%data(df) + proxy1%data(df) lhs = arg_refs[0] rhs = BinaryOperation.create(BinaryOperation.Operator.ADD, lhs.copy(), arg_refs[1]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicAPlusXKern(LFRicBuiltIn): ''' `Y = a + X` where `a` is a real scalar and `X` and `Y` are real-valued fields (DoF-wise addition of a scalar value). ''' _case_name = "a_plus_X" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"), ScalarArgMetadata(gh_datatype, "gh_read"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = ascalar + proxy1%data(df) lhs = arg_refs[0] rhs = BinaryOperation.create(BinaryOperation.Operator.ADD, scalar_args[0], arg_refs[1]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicIncAPlusXKern(LFRicBuiltIn): ''' `X = a + X` where `a` is a real scalar and `X` is a real-valued field (DoF-wise addition of a scalar value). ''' _case_name = "inc_a_plus_X" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ ScalarArgMetadata(gh_datatype, "gh_read"), FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1")])
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = ascalar + proxy0%data(df) lhs = arg_refs[0] rhs = BinaryOperation.create(BinaryOperation.Operator.ADD, scalar_args[0], lhs.copy()) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicAXPlusYKern(LFRicBuiltIn): ''' `Z = a*X + Y` where `a` is a real scalar and `Z`, `X` and `Y` are real-valued fields. ''' _case_name = "aX_plus_Y" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"), ScalarArgMetadata(gh_datatype, "gh_read"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = ascalar * proxy1%data(df) + proxy2%data(df) lhs = arg_refs[0] mult_op = BinaryOperation.create(BinaryOperation.Operator.MUL, scalar_args[0], arg_refs[1]) rhs = BinaryOperation.create(BinaryOperation.Operator.ADD, mult_op, arg_refs[2]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicIncAXPlusYKern(LFRicBuiltIn): ''' `X = a*X + Y` where `a` is a real scalar and `X` and `Y` are real-valued fields. ''' _case_name = "inc_aX_plus_Y" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ ScalarArgMetadata(gh_datatype, "gh_read"), FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = ascalar * proxy0%data(df) + proxy1%data(df) lhs = arg_refs[0] mult_op = BinaryOperation.create(BinaryOperation.Operator.MUL, scalar_args[0], lhs.copy()) rhs = BinaryOperation.create(BinaryOperation.Operator.ADD, mult_op, arg_refs[1]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicIncXPlusBYKern(LFRicBuiltIn): ''' `X = X + b*Y` where `b` is a real scalar and `X` and `Y` are real-valued fields. ''' _case_name = "inc_X_plus_bY" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1"), ScalarArgMetadata(gh_datatype, "gh_read"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = proxy0%data(df) + bscalar * proxy1%data(df) lhs = arg_refs[0] mult_op = BinaryOperation.create(BinaryOperation.Operator.MUL, scalar_args[0], arg_refs[1]) rhs = BinaryOperation.create(BinaryOperation.Operator.ADD, lhs.copy(), mult_op) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicAXPlusBYKern(LFRicBuiltIn): ''' `Z = a*X + b*Y` where `a` and `b` are real scalars and `Z`, `X` and `Y` are real-valued fields. ''' _case_name = "aX_plus_bY" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"), ScalarArgMetadata(gh_datatype, "gh_read"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1"), ScalarArgMetadata(gh_datatype, "gh_read"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = ascalar * proxy1%data(df) + # bscalar *proxy2%data(df) lhs = arg_refs[0] mult_op_a = BinaryOperation.create(BinaryOperation.Operator.MUL, scalar_args[0], arg_refs[1]) mult_op_b = BinaryOperation.create(BinaryOperation.Operator.MUL, scalar_args[1], arg_refs[2]) rhs = BinaryOperation.create(BinaryOperation.Operator.ADD, mult_op_a, mult_op_b) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicIncAXPlusBYKern(LFRicBuiltIn): ''' `X = a*X + b*Y` where `a` and `b` are real scalars and `X` and `Y` are real-valued fields. ''' _case_name = "inc_aX_plus_bY" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ ScalarArgMetadata(gh_datatype, "gh_read"), FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1"), ScalarArgMetadata(gh_datatype, "gh_read"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = ascalar * proxy0%data(df) + # bscalar * proxy1%data(df) lhs = arg_refs[0] mult_op_a = BinaryOperation.create(BinaryOperation.Operator.MUL, scalar_args[0], lhs.copy()) mult_op_b = BinaryOperation.create(BinaryOperation.Operator.MUL, scalar_args[1], arg_refs[1]) rhs = BinaryOperation.create(BinaryOperation.Operator.ADD, mult_op_a, mult_op_b) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicAXPlusAYKern(LFRicBuiltIn): ''' `Z = a*X + a*Y = a*(X + Y)` where `a` is a real scalar and `Z`, `X` and `Y` are real-valued fields. ''' _case_name = "aX_plus_aY" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"), ScalarArgMetadata(gh_datatype, "gh_read"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = ascalar * (proxy1%data(df) + proxy2%data(df)) lhs = arg_refs[0] add_op = BinaryOperation.create(BinaryOperation.Operator.ADD, arg_refs[1], arg_refs[2]) rhs = BinaryOperation.create(BinaryOperation.Operator.MUL, scalar_args[0], add_op) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
# ------------------------------------------------------------------- # # ============== Subtracting (scaled) real fields =================== # # ------------------------------------------------------------------- #
[docs] class LFRicXMinusYKern(LFRicBuiltIn): ''' Subtract one, real-valued, field from another and return the result as a third, real-valued, field. ''' _case_name = "X_minus_Y" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
def __str__(self): return (f"Built-in: {self._case_name} (subtract " f"{self._datatype}-valued fields)")
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = proxy1%data(df) - proxy2%data(df) lhs = arg_refs[0] rhs = BinaryOperation.create(BinaryOperation.Operator.SUB, arg_refs[1], arg_refs[2]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicIncXMinusYKern(LFRicBuiltIn): ''' Subtract the second, real-valued, field from the first field and return it. ''' _case_name = "inc_X_minus_Y" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
def __str__(self): return (f"Built-in: {self._case_name} (decrement " f"{a_or_an(self._datatype)} {self._datatype}-valued field)")
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed refs for both of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = proxy0%data(df) - proxy1%data(df) lhs = arg_refs[0] rhs = BinaryOperation.create(BinaryOperation.Operator.SUB, lhs.copy(), arg_refs[1]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicAMinusXKern(LFRicBuiltIn): ''' `Y = a - X` where `a` is a real scalar and `X` and `Y` are real-valued fields (DoF-wise subtraction of field elements from a scalar value). ''' _case_name = "a_minus_X" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"), ScalarArgMetadata(gh_datatype, "gh_read"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = ascalar - proxy1%data(df) lhs = arg_refs[0] rhs = BinaryOperation.create(BinaryOperation.Operator.SUB, scalar_args[0], arg_refs[1]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicIncAMinusXKern(LFRicBuiltIn): ''' `X = a - X` where `a` is a real scalar and `X` is a real-valued field (DoF-wise subtraction of field elements from a scalar value). ''' _case_name = "inc_a_minus_X" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ ScalarArgMetadata(gh_datatype, "gh_read"), FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1")])
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = ascalar - proxy0%data(df) lhs = arg_refs[0] rhs = BinaryOperation.create(BinaryOperation.Operator.SUB, scalar_args[0], lhs.copy()) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicXMinusAKern(LFRicBuiltIn): ''' `Y = X - a` where `a` is a real scalar and `X` and `Y` are real-valued fields (DoF-wise subtraction of a scalar value from field elements). ''' _case_name = "X_minus_a" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1"), ScalarArgMetadata(gh_datatype, "gh_read")])
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = proxy1%data(df) - ascalar lhs = arg_refs[0] rhs = BinaryOperation.create(BinaryOperation.Operator.SUB, arg_refs[1], scalar_args[0]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicIncXMinusAKern(LFRicBuiltIn): ''' `X = X - a` where `a` is a real scalar and `X` is a real-valued field (DoF-wise subtraction of a scalar value from field elements). ''' _case_name = "inc_X_minus_a" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1"), ScalarArgMetadata(gh_datatype, "gh_read")])
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = proxy0%data(df) - ascalar lhs = arg_refs[0] rhs = BinaryOperation.create(BinaryOperation.Operator.SUB, lhs.copy(), scalar_args[0]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicAXMinusYKern(LFRicBuiltIn): ''' `Z = a*X - Y` where `a` is a real scalar and `Z`, `X` and `Y` are real-valued fields. ''' _case_name = "aX_minus_Y" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"), ScalarArgMetadata(gh_datatype, "gh_read"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = ascalar * proxy1%data(df) - proxy2%data(df) lhs = arg_refs[0] mult_op = BinaryOperation.create(BinaryOperation.Operator.MUL, scalar_args[0], arg_refs[1]) rhs = BinaryOperation.create(BinaryOperation.Operator.SUB, mult_op, arg_refs[2]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicXMinusBYKern(LFRicBuiltIn): ''' `Z = X - b*Y` where `b` is a real scalar and `Z`, `X` and `Y` are real-valued fields. ''' _case_name = "X_minus_bY" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1"), ScalarArgMetadata(gh_datatype, "gh_read"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = proxy1%data(df) - bscalar * proxy2%data(df) lhs = arg_refs[0] mult_op = BinaryOperation.create(BinaryOperation.Operator.MUL, scalar_args[0], arg_refs[2]) rhs = BinaryOperation.create(BinaryOperation.Operator.SUB, arg_refs[1], mult_op) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicIncXMinusBYKern(LFRicBuiltIn): ''' `X = X - b*Y` where `b` is a real scalar and `X` and `Y` are real-valued fields. ''' _case_name = "inc_X_minus_bY" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1"), ScalarArgMetadata(gh_datatype, "gh_read"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = proxy0%data(df) - bscalar * proxy1%data(df) lhs = arg_refs[0] mult_op = BinaryOperation.create(BinaryOperation.Operator.MUL, scalar_args[0], arg_refs[1]) rhs = BinaryOperation.create(BinaryOperation.Operator.SUB, lhs.copy(), mult_op) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicAXMinusBYKern(LFRicBuiltIn): ''' `Z = a*X - b*Y` where `a` and `b` are real scalars and `Z`, `X` and `Y` are real-valued fields. ''' _case_name = "aX_minus_bY" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"), ScalarArgMetadata(gh_datatype, "gh_read"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1"), ScalarArgMetadata(gh_datatype, "gh_read"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = ascalar * proxy1%data(df) - # bscalar * proxy2%data(df) lhs = arg_refs[0] mult_op_a = BinaryOperation.create(BinaryOperation.Operator.MUL, scalar_args[0], arg_refs[1]) mult_op_b = BinaryOperation.create(BinaryOperation.Operator.MUL, scalar_args[1], arg_refs[2]) rhs = BinaryOperation.create(BinaryOperation.Operator.SUB, mult_op_a, mult_op_b) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
# ------------------------------------------------------------------- # # ============== Multiplying (scaled) real fields =================== # # ------------------------------------------------------------------- #
[docs] class LFRicXTimesYKern(LFRicBuiltIn): ''' DoF-wise product of one, real-valued, field with another with the result returned as a third, real-valued, field. ''' _case_name = "X_times_Y" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
def __str__(self): return (f"Built-in: {self._case_name} (multiply " f"{self._datatype}-valued fields)")
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = proxy1%data(df) * proxy2%data(df) lhs = arg_refs[0] rhs = BinaryOperation.create(BinaryOperation.Operator.MUL, arg_refs[1], arg_refs[2]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicIncXTimesYKern(LFRicBuiltIn): ''' Multiply the first, real-valued, field by the second and return it. ''' _case_name = "inc_X_times_Y" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
def __str__(self): return (f"Built-in: {self._case_name} (multiply one " f"{self._datatype}-valued field by another)")
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed refs for both of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = proxy0%data(df) * proxy1%data(df) lhs = arg_refs[0] rhs = BinaryOperation.create(BinaryOperation.Operator.MUL, lhs.copy(), arg_refs[1]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicIncAXTimesYKern(LFRicBuiltIn): ''' `X = a*X*Y` where `a` is a real scalar and `X` and `Y` are real-valued fields. ''' _case_name = "inc_aX_times_Y" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ ScalarArgMetadata(gh_datatype, "gh_read"), FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = ascalar * proxy0%data(df) * proxy1%data(df) lhs = arg_refs[0] mult_op = BinaryOperation.create(BinaryOperation.Operator.MUL, scalar_args[0], lhs.copy()) rhs = BinaryOperation.create(BinaryOperation.Operator.MUL, mult_op, arg_refs[1]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
# ------------------------------------------------------------------- # # ============== Scaling real fields ================================ # # ------------------------------------------------------------------- #
[docs] class LFRicATimesXKern(LFRicBuiltIn): ''' Multiply the first, real-valued, field by a real scalar and return the result as a second, real-valued, field (`Y = a*X`). ''' _case_name = "a_times_X" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"), ScalarArgMetadata(gh_datatype, "gh_read"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
def __str__(self): return (f"Built-in: {self._case_name} (copy a scaled " f"{self._datatype}-valued field)")
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = ascalar * proxy1%data(df) lhs = arg_refs[0] rhs = BinaryOperation.create(BinaryOperation.Operator.MUL, scalar_args[0], arg_refs[1]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicIncATimesXKern(LFRicBuiltIn): ''' Multiply a real-valued field by a real scalar and return it. ''' _case_name = "inc_a_times_X" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ ScalarArgMetadata(gh_datatype, "gh_read"), FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1")])
def __str__(self): return (f"Built-in: {self._case_name} (scale " f"{a_or_an(self._datatype)} {self._datatype}-valued field)")
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = ascalar * proxy0%data(df) lhs = arg_refs[0] rhs = BinaryOperation.create(BinaryOperation.Operator.MUL, scalar_args[0], lhs.copy()) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
# ------------------------------------------------------------------- # # ============== Dividing real fields =============================== # # ------------------------------------------------------------------- #
[docs] class LFRicXDividebyYKern(LFRicBuiltIn): ''' Divide the first, real-valued, field by the second and return the result as a third, real-valued, field. ''' _case_name = "X_divideby_Y" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
def __str__(self): return (f"Built-in: {self._case_name} (divide " f"{self._datatype}-valued fields)")
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = proxy1%data(df) / proxy2%data(df) lhs = arg_refs[0] rhs = BinaryOperation.create(BinaryOperation.Operator.DIV, arg_refs[1], arg_refs[2]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicIncXDividebyYKern(LFRicBuiltIn): ''' Divide the first, real-valued, field by the second and return it. ''' _case_name = "inc_X_divideby_Y" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
def __str__(self): return (f"Built-in: {self._case_name} (divide one " f"{self._datatype}-valued field by another)")
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed refs for both of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = proxy0%data(df) / proxy1%data(df) lhs = arg_refs[0] rhs = BinaryOperation.create(BinaryOperation.Operator.DIV, lhs.copy(), arg_refs[1]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicXDividebyAKern(LFRicBuiltIn): ''' Divide a real-valued field by a real scalar and return the result in another, real-valued, field. ''' _case_name = "X_divideby_a" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1"), ScalarArgMetadata(gh_datatype, "gh_read")])
def __str__(self): return (f"Built-in: {self._case_name} (divide a real-valued field " f"by {a_or_an(self._datatype)} {self._datatype} scalar " "(Y = X/a))")
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = proxy1%data(df) / ascalar lhs = arg_refs[0] rhs = BinaryOperation.create(BinaryOperation.Operator.DIV, arg_refs[1], scalar_args[0]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicIncXDividebyAKern(LFRicBuiltIn): ''' Divide a real-valued field by a real scalar and return it. ''' _case_name = "inc_X_divideby_a" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1"), ScalarArgMetadata(gh_datatype, "gh_read")])
def __str__(self): return (f"Built-in: {self._case_name} (divide a real-valued field " f"by {a_or_an(self._datatype)} {self._datatype} scalar " f"(X = X/a))")
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = proxy0%data(df) / ascalar lhs = arg_refs[0] rhs = BinaryOperation.create(BinaryOperation.Operator.DIV, lhs.copy(), scalar_args[0]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
# ------------------------------------------------------------------- # # ============== Inverse scaling of real fields ===================== # # ------------------------------------------------------------------- #
[docs] class LFRicADividebyXKern(LFRicBuiltIn): ''' DoF-wise division of a scalar value `a` by the elements of a real-valued field, `X`, storing the result in another, real-valued, field, `Y` (`Y = a/X`). ''' _case_name = "a_divideby_X" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"), ScalarArgMetadata(gh_datatype, "gh_read"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
def __str__(self): return (f"Built-in: {self._case_name} (inverse scaling of " f"{a_or_an(self._datatype)} {self._datatype}-valued " f"field (Y = a/X))")
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = ascalar / proxy1%data(df) lhs = arg_refs[0] rhs = BinaryOperation.create(BinaryOperation.Operator.DIV, scalar_args[0], arg_refs[1]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicIncADividebyXKern(LFRicBuiltIn): ''' DoF-wise division of a scalar value `a` by the elements of a real-valued field, `X`, storing the result in the same field (`X = a/X`). ''' _case_name = "inc_a_divideby_X" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ ScalarArgMetadata(gh_datatype, "gh_read"), FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1")])
def __str__(self): return (f"Built-in: {self._case_name} (inverse scaling of " f"{a_or_an(self._datatype)} {self._datatype}-valued " f"field (X = a/X))")
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = ascalar / proxy0%data(df) lhs = arg_refs[0] rhs = BinaryOperation.create(BinaryOperation.Operator.DIV, scalar_args[0], lhs.copy()) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
# ------------------------------------------------------------------- # # ============== Raising a real field to a scalar =================== # # ------------------------------------------------------------------- #
[docs] class LFRicIncXPowrealAKern(LFRicBuiltIn): ''' Raise a real-valued field to a real power and return it. ''' _case_name = "inc_X_powreal_a" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1"), ScalarArgMetadata("gh_real", "gh_read")])
def __str__(self): return (f"Built-in: {self._case_name} (raise " f"{a_or_an(self._datatype)} {self._datatype}-valued field " f"to a real power)")
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get PSyIR for each of the arguments. arg_refs = self.get_indexed_field_argument_references() scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = proxy0%data(df) ** real_power lhs = arg_refs[0] rhs = BinaryOperation.create(BinaryOperation.Operator.POW, lhs.copy(), scalar_args[0]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicIncXPowintNKern(LFRicBuiltIn): ''' Raise a real-valued field to an integer power and return it. ''' _case_name = "inc_X_powint_n" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1"), ScalarArgMetadata("gh_integer", "gh_read")])
def __str__(self): return (f"Built-in: {self._case_name} (raise " f"{a_or_an(self._datatype)} {self._datatype}-valued field " f"to an integer power)")
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get PSyIR for each of the arguments. arg_refs = self.get_indexed_field_argument_references() scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = proxy0%data(df) ** int_power lhs = arg_refs[0] rhs = BinaryOperation.create(BinaryOperation.Operator.POW, lhs.copy(), scalar_args[0]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
# ------------------------------------------------------------------- # # ============== Setting real field elements to a value ============ # # ------------------------------------------------------------------- #
[docs] class LFRicSetvalCKern(LFRicBuiltIn): ''' Set a real-valued field equal to a real scalar value. ''' _case_name = "setval_c" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"), ScalarArgMetadata(gh_datatype, "gh_read")])
def __str__(self): return (f"Built-in: {self._case_name} (set {a_or_an(self._datatype)} " f"{self._datatype}-valued field to a {self._datatype} " f"scalar value)")
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = ascalar lhs = arg_refs[0] rhs = scalar_args[0] # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicSetvalXKern(LFRicBuiltIn): ''' Set a real-valued field equal to another, real-valued, field. ''' _case_name = "setval_X" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
def __str__(self): return (f"Built-in: {self._case_name} (set {a_or_an(self._datatype)} " f"{self._datatype}-valued field equal to another such field)")
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed refs for both of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = proxy1%data(df) lhs = arg_refs[0] rhs = arg_refs[1] # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicSetvalRandomKern(LFRicBuiltIn): ''' Fill a real-valued field with pseudo-random numbers. ''' _case_name = "setval_random" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_write", "any_space_1")])
def __str__(self): return (f"Built-in: {self._case_name} (fill {a_or_an(self._datatype)} " f"{self._datatype}-valued field with pseudo-random numbers)")
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an IntrinsicCall node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed refs for the field (proxy) argument. arg_refs = self.get_indexed_field_argument_references() # Create the PSyIR for the kernel: # call random_number(proxy0%data(df)) call = IntrinsicCall.create(IntrinsicCall.Intrinsic.RANDOM_NUMBER, arg_refs) # Add a preceding comment to the Assignment call.preceding_comment = str(self) # Finally, replace this kernel node with the Assignment self.replace_with(call) return call
# ------------------------------------------------------------------- # # ============== Inner product of real fields ======================= # # ------------------------------------------------------------------- #
[docs] class LFRicXInnerproductYKern(LFRicBuiltIn): ''' Calculates the inner product of two real-valued fields, `innprod = SUM( X(:)*Y(:) )`. ''' _case_name = "X_innerproduct_Y" _datatype = "real" _reduction_type = LFRicBuiltIn.ReductionType.SUM
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ ScalarArgMetadata(gh_datatype, "gh_reduction"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for the field (proxy) argument. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar reduction argument. lhs = self._reduction_reference() # Create the PSyIR for the kernel: # asum = asum + proxy0%data(df) * proxy1%data(df) mult_op = BinaryOperation.create(BinaryOperation.Operator.MUL, arg_refs[0], arg_refs[1]) rhs = BinaryOperation.create(BinaryOperation.Operator.ADD, lhs.copy(), mult_op) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicXInnerproductXKern(LFRicBuiltIn): ''' Calculates the inner product of one real-valued field by itself, `innprod = SUM( X(:)*X(:) )`. ''' _case_name = "X_innerproduct_X" _datatype = "real" _reduction_type = LFRicBuiltIn.ReductionType.SUM
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ ScalarArgMetadata(gh_datatype, "gh_reduction"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for the field (proxy) argument. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar reduction argument. lhs = self._reduction_reference() # Create the PSyIR for the kernel: # asum = asum + proxy0%data(df) * proxy0%data(df) mult_op = BinaryOperation.create(BinaryOperation.Operator.MUL, arg_refs[0].copy(), arg_refs[0]) rhs = BinaryOperation.create(BinaryOperation.Operator.ADD, lhs.copy(), mult_op) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
# ------------------------------------------------------------------- # # ============== Sum of real field elements ========================= # # ------------------------------------------------------------------- #
[docs] class LFRicSumXKern(LFRicBuiltIn): ''' Computes the sum of the elements of a real-valued field. ''' _case_name = "sum_X" _datatype = "real" _reduction_type = LFRicBuiltIn.ReductionType.SUM
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ ScalarArgMetadata(gh_datatype, "gh_reduction"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
def __str__(self): return (f"Built-in: {self._case_name} (sum {a_or_an(self._datatype)} " f"{self._datatype}-valued field)")
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for the field (proxy) argument. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar reduction argument. lhs = self._reduction_reference() # Create the PSyIR for the kernel: # asum = asum + proxy0%data(df) rhs = BinaryOperation.create(BinaryOperation.Operator.ADD, lhs.copy(), arg_refs[0]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
# ------------------------------------------------------------------- # # ============== Sign of real field elements ======================== # # ------------------------------------------------------------------- #
[docs] class LFRicSignXKern(LFRicBuiltIn): ''' Returns the sign of a real-valued field elements using the Fortran intrinsic `sign` function, `Y = sign(a, X)`. ''' _case_name = "sign_X" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"), ScalarArgMetadata(gh_datatype, "gh_read"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
def __str__(self): return (f"Built-in: {self._case_name} (sign of " f"{a_or_an(self._datatype)} {self._datatype}-valued field, " f"applied to a scalar argument)")
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = SIGN(ascalar, proxy1%data) lhs = arg_refs[0] rhs = IntrinsicCall.create(IntrinsicCall.Intrinsic.SIGN, [scalar_args[0], arg_refs[1]]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
# ------------------------------------------------------------------- # # ============== Maximum of (real scalar, real field elements) ====== # # ------------------------------------------------------------------- #
[docs] class LFRicMaxAXKern(LFRicBuiltIn): ''' Returns the maximum of a real scalar and real-valued field elements. The result is stored as another, real-valued, field: `Y = max(a, X)`. ''' _case_name = "max_aX" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"), ScalarArgMetadata(gh_datatype, "gh_read"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = MAX(ascalar, proxy1%data) lhs = arg_refs[0] rhs = IntrinsicCall.create(IntrinsicCall.Intrinsic.MAX, [scalar_args[0], arg_refs[1]]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicIncMaxAXKern(LFRicBuiltIn): ''' Returns the maximum of a real scalar and real-valued field elements. The result is stored in the same, real-valued, field: `X = max(a, X)`. ''' _case_name = "inc_max_aX" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ ScalarArgMetadata(gh_datatype, "gh_read"), FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1")])
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = MAX(ascalar, proxy0%data) lhs = arg_refs[0] rhs = IntrinsicCall.create(IntrinsicCall.Intrinsic.MAX, [scalar_args[0], lhs.copy()]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
# ------------------------------------------------------------------- # # ============== Minimum of (real scalar, real field elements) ====== # # ------------------------------------------------------------------- #
[docs] class LFRicMinAXKern(LFRicBuiltIn): ''' Returns the minimum of a real scalar and real-valued field elements. The result is stored as another, real-valued, field: `Y = min(a, X)`. ''' _case_name = "min_aX" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"), ScalarArgMetadata(gh_datatype, "gh_read"), FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = MIN(ascalar, proxy1%data) lhs = arg_refs[0] rhs = IntrinsicCall.create(IntrinsicCall.Intrinsic.MIN, [scalar_args[0], arg_refs[1]]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
[docs] class LFRicIncMinAXKern(LFRicBuiltIn): ''' Returns the minimum of a real scalar and real-valued field elements. The result is stored in the same, real-valued, field: `X = min(a, X)`. ''' _case_name = "inc_min_aX" _datatype = "real"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype] return cls._builtin_metadata([ ScalarArgMetadata(gh_datatype, "gh_read"), FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1")])
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar argument. scalar_args = self.get_scalar_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = MIN(ascalar, proxy0%data) lhs = arg_refs[0] rhs = IntrinsicCall.create(IntrinsicCall.Intrinsic.MIN, [scalar_args[0], lhs.copy()]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
# ------------------------------------------------------------------- # # ============ Minimum, maximum value of real field elements) ======= # # ------------------------------------------------------------------- # class LFRicMinvalXKern(LFRicBuiltIn): ''' Computes the (global) minimum scalar value held in the supplied field. ''' _case_name = "minval_X" _datatype = "real" _reduction_type = LFRicBuiltIn.ReductionType.MIN @classmethod def metadata(cls) -> LFRicKernelMetadata: """ :returns: kernel metadata describing this built-in. """ return cls._builtin_metadata([ ScalarArgMetadata("gh_real", "gh_reduction"), FieldArgMetadata("gh_real", "gh_read", "any_space_1")]) def __str__(self): return (f"Built-in: {self._case_name} (compute the global minimum " f"value contained in a field)") def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for the field (proxy) argument. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar reduction argument. lhs = self._reduction_reference() minval = IntrinsicCall.create(IntrinsicCall.Intrinsic.MIN, [lhs.copy(), arg_refs[0]]) return self._replace_with_assignment(lhs, minval) class LFRicMaxvalXKern(LFRicBuiltIn): ''' Computes the (global) maximum scalar value held in the supplied field. ''' _case_name = "maxval_X" _datatype = "real" _reduction_type = LFRicBuiltIn.ReductionType.MAX @classmethod def metadata(cls) -> LFRicKernelMetadata: """ :returns: kernel metadata describing this built-in. """ return cls._builtin_metadata([ ScalarArgMetadata("gh_real", "gh_reduction"), FieldArgMetadata("gh_real", "gh_read", "any_space_1")]) def __str__(self): return (f"Built-in: {self._case_name} (compute the global maximum " f"value contained in a field)") def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for the field (proxy) argument. arg_refs = self.get_indexed_field_argument_references() # Get a reference for the kernel scalar reduction argument. lhs = self._reduction_reference() minval = IntrinsicCall.create(IntrinsicCall.Intrinsic.MAX, [lhs.copy(), arg_refs[0]]) return self._replace_with_assignment(lhs, minval) # ------------------------------------------------------------------- # # ============== Converting real to integer field elements ========== # # ------------------------------------------------------------------- #
[docs] class LFRicRealToIntXKern(LFRicBuiltIn): ''' Converts real-valued field elements to integer-valued field elements using the Fortran intrinsic `INT` function, `Y = INT(X, kind=i_<prec>)`. Here `Y` is an integer-valued field of precision `i_<prec>` and `X` is the real-valued field being converted. ''' _datatype = "integer" _case_name = "real_to_int_X"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' return cls._builtin_metadata([ FieldArgMetadata("gh_integer", "gh_write", "any_space_1"), FieldArgMetadata("gh_real", "gh_read", "any_space_1")])
def __str__(self): return (f"Built-in: {self._case_name} (convert a real-valued to " f"an integer-valued field)")
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = INT(proxy1%data, kind=i_<prec>) lhs = arg_refs[0] datatype = arg_refs[0].symbol.datatype if isinstance(datatype, UnsupportedFortranType): datatype = datatype.partial_datatype rhs = IntrinsicCall.create( IntrinsicCall.Intrinsic.INT, [arg_refs[1], ("kind", datatype.precision.copy())]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
# ------------------------------------------------------------------- # # ============== Converting real to real field elements ============= # # ------------------------------------------------------------------- #
[docs] class LFRicRealToRealXKern(LFRicBuiltIn): ''' Converts real-valued field elements to real-valued field elements of a different precision using the Fortran intrinsic `REAL` function, `Y = REAL(X, kind=r_<prec>)`. Here `Y` is a real-valued field of precision `kind=r_<prec>` and `X` is the real-valued field whose values are to be converted from their defined precision. ''' _datatype = "real" _case_name = "real_to_real_X"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' return cls._builtin_metadata([ FieldArgMetadata("gh_real", "gh_write", "any_space_1"), FieldArgMetadata("gh_real", "gh_read", "any_space_1")])
def __str__(self): return (f"Built-in: {self._case_name} (convert a real-valued " f"to a real-valued field)")
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = REAL(proxy1%data, kind=r_<prec>) lhs = arg_refs[0] datatype = arg_refs[0].symbol.datatype if isinstance(datatype, UnsupportedFortranType): datatype = datatype.partial_datatype rhs = IntrinsicCall.create( IntrinsicCall.Intrinsic.REAL, [arg_refs[1], ("kind", datatype.precision.copy())]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
# ******************************************************************* # # ************** Built-ins for integer-valued fields **************** # # ******************************************************************* # # ------------------------------------------------------------------- # # ============== Adding integer fields ============================== # # ------------------------------------------------------------------- #
[docs] class LFRicIntXPlusYKern(LFRicXPlusYKern): ''' Add corresponding elements of two, integer-valued, fields, `X` and `Y`, and return the result as a third, integer-valued, field, `Z`. Inherits the `lower_to_language_level` method from the real-valued built-in equivalent `LFRicXPlusYKern`. ''' _case_name = "int_X_plus_Y" _datatype = "integer"
[docs] class LFRicIntIncXPlusYKern(LFRicIncXPlusYKern): ''' Add each element of an integer-valued field, `X`, to the corresponding element of another integer-valued field, `Y`, and store the result back in `X`. Inherits the `lower_to_language_level` method from the real-valued built-in equivalent `LFRicIncXPlusYKern`. ''' _case_name = "int_inc_X_plus_Y" _datatype = "integer"
[docs] class LFRicIntAPlusXKern(LFRicAPlusXKern): ''' Add an integer scalar value, `a`, to each element of an integer-valued field, `X`, and return the result as a second, integer-valued, field, `Y`. Inherits the `lower_to_language_level` method from the real-valued built-in equivalent `LFRicAPlusXKern`. ''' _case_name = "int_a_plus_X" _datatype = "integer"
[docs] class LFRicIntIncAPlusXKern(LFRicIncAPlusXKern): ''' Add an integer scalar value, `a`, to each element of an integer-valued field, `X`, and return the result in the same field. Inherits the `lower_to_language_level` method from the real-valued built-in equivalent `LFRicIncAPlusXKern`. ''' _case_name = "int_inc_a_plus_X" _datatype = "integer"
# ------------------------------------------------------------------- # # ============== Subtracting integer fields ========================= # # ------------------------------------------------------------------- #
[docs] class LFRicIntXMinusYKern(LFRicXMinusYKern): ''' Subtract each element of an integer-valued field, `Y`, from the corresponding element of another, integer-valued, field, `X`, and return the result as a third, integer-valued, field, `Z`. Inherits the `lower_to_language_level` method from the real-valued built-in equivalent `LFRicXMinusYKern`. ''' _case_name = "int_X_minus_Y" _datatype = "integer"
[docs] class LFRicIntIncXMinusYKern(LFRicIncXMinusYKern): ''' Subtract each element of an integer-valued field, `Y`, from the corresponding element of another, integer-valued, field, `X`, and store the result back in `X`. Inherits the `lower_to_language_level` method from the real-valued built-in equivalent `LFRicIncXMinusYKern`. ''' _case_name = "int_inc_X_minus_Y" _datatype = "integer"
[docs] class LFRicIntAMinusXKern(LFRicAMinusXKern): ''' Subtract each element of an integer-valued field, `X`, from an integer scalar value, `a`, and return the result as a second, integer-valued, field, `Y`. Inherits the `lower_to_language_level` method from the real-valued built-in equivalent `LFRicAMinusXKern`. ''' _case_name = "int_a_minus_X" _datatype = "integer"
[docs] class LFRicIntIncAMinusXKern(LFRicIncAMinusXKern): ''' Subtract each element of an integer-valued field, `X`, from an integer scalar value, `a`, and return the result in the same field. Inherits the `lower_to_language_level` method from the real-valued built-in equivalent `LFRicIncAMinusXKern`. ''' _case_name = "int_inc_a_minus_X" _datatype = "integer"
[docs] class LFRicIntXMinusAKern(LFRicXMinusAKern): ''' Subtract an integer scalar value, `a`, from each element of an integer-valued field, `X`, and return the result as a second, integer-valued, field, `Y`. Inherits the `lower_to_language_level` method from the real-valued built-in equivalent `LFRicXMinusAKern`. ''' _case_name = "int_X_minus_a" _datatype = "integer"
[docs] class LFRicIntIncXMinusAKern(LFRicIncXMinusAKern): ''' Subtract an integer scalar value, `a`, from each element of an integer-valued field, `X`, and return the result in the same field. Inherits the `lower_to_language_level` method from the real-valued built-in equivalent `LFRicIncXMinusAKern`. ''' _case_name = "int_inc_X_minus_a" _datatype = "integer"
# ------------------------------------------------------------------- # # ============== Multiplying integer fields ========================= # # ------------------------------------------------------------------- #
[docs] class LFRicIntXTimesYKern(LFRicXTimesYKern): ''' Multiply each element of one, integer-valued, field, `X`, by the corresponding element of another, integer-valued, field, `Y`, and return the result as a third, integer-valued, field, `Z`. Inherits the `lower_to_language_level` method from the real-valued built-in equivalent `LFRicXTimesYKern`. ''' _case_name = "int_X_times_Y" _datatype = "integer"
[docs] class LFRicIntIncXTimesYKern(LFRicIncXTimesYKern): ''' Multiply each element of one, integer-valued, field, `X`, by the corresponding element of another, integer-valued, field, `Y`, and store the result back in `X`. Inherits the `lower_to_language_level` method from the real-valued built-in equivalent `LFRicIncXTimesYKern`. ''' _case_name = "int_inc_X_times_Y" _datatype = "integer"
# ------------------------------------------------------------------- # # ============== Scaling integer fields ============================= # # ------------------------------------------------------------------- #
[docs] class LFRicIntATimesXKern(LFRicATimesXKern): ''' Multiply each element of the first, integer-valued, field, `X`, by an integer scalar, `a`, and return the result as a second, integer-valued, field `Y` (`Y = a*X`). Inherits the `lower_to_language_level` method from the real-valued built-in equivalent `LFRicATimesXKern`. ''' _case_name = "int_a_times_X" _datatype = "integer"
[docs] class LFRicIntIncATimesXKern(LFRicIncATimesXKern): ''' Multiply each element of an integer-valued field, `X` by an integer scalar, `a`, and store the result back in `X`. Inherits the `lower_to_language_level` method from the real-valued built-in equivalent `LFRicIncATimesXKern`. ''' _case_name = "int_inc_a_times_X" _datatype = "integer"
# ------------------------------------------------------------------- # # ============== Setting integer field elements to a value ========= # # ------------------------------------------------------------------- #
[docs] class LFRicIntSetvalCKern(LFRicSetvalCKern): ''' Assign a single constant integer scalar value, `c`, to all elements of an integer-valued field, `X`. Inherits the `lower_to_language_level` method from the real-valued built-in equivalent `LFRicSetvalCKern`. ''' _case_name = "int_setval_c" _datatype = "integer"
[docs] class LFRicIntSetvalXKern(LFRicSetvalXKern): ''' Copy one element of an integer-valued field (second argument), `X`, to the corresponding element of another, integer-valued, field (first argument), `Y`. Inherits the `lower_to_language_level` method from the real-valued built-in equivalent `LFRicSetvalXKern`. ''' _case_name = "int_setval_X" _datatype = "integer"
# ------------------------------------------------------------------- # # ============== Sign of integer field elements ===================== # # ------------------------------------------------------------------- #
[docs] class LFRicIntSignXKern(LFRicSignXKern): ''' Returns the sign of an integer-valued field elements using the Fortran intrinsic `sign` function, `Y = sign(a, X)`. Inherits the `lower_to_language_level` method from the real-valued built-in equivalent `LFRicSignXKern`. ''' _case_name = "int_sign_X" _datatype = "integer"
# ------------------------------------------------------------------- # # ======== Maximum of (integer scalar, integer field elements) ====== # # ------------------------------------------------------------------- #
[docs] class LFRicIntMaxAXKern(LFRicMaxAXKern): ''' Returns the maximum of an integer scalar and integer-valued field elements. The result is stored as another, integer-valued, field: `Y = max(a, X)`. Inherits the `lower_to_language_level` method from the real-valued built-in equivalent `LFRicMaxAXKern`. ''' _case_name = "int_max_aX" _datatype = "integer"
[docs] class LFRicIntIncMaxAXKern(LFRicIncMaxAXKern): ''' Returns the maximum of an integer scalar and integer-valued field elements. The result is stored in the same, integer-valued, field: `X = max(a, X)`. Inherits the `lower_to_language_level` method from the real-valued built-in equivalent `LFRicIncMaxAXKern`. ''' _case_name = "int_inc_max_aX" _datatype = "integer"
# ------------------------------------------------------------------- # # ======== Minimum of (integer scalar, integer field elements) ====== # # ------------------------------------------------------------------- #
[docs] class LFRicIntMinAXKern(LFRicMinAXKern): ''' Returns the minimum of an integer scalar and integer-valued field elements. The result is stored as another, integer-valued, field: `Y = min(a, X)`. Inherits the `lower_to_language_level` method from the real-valued built-in equivalent `LFRicMinAXKern`. ''' _case_name = "int_min_aX" _datatype = "integer"
[docs] class LFRicIntIncMinAXKern(LFRicIncMinAXKern): ''' Returns the minimum of an integer scalar and integer-valued field elements. The result is stored in the same, integer-valued, field: `X = min(a, X)`. Inherits the `lower_to_language_level` method from the real-valued built-in equivalent `LFRicIncMinAXKern`. ''' _case_name = "int_inc_min_aX" _datatype = "integer"
# ------------------------------------------------------------------- # # ============== Converting integer to real field elements ========== # # ------------------------------------------------------------------- #
[docs] class LFRicIntToRealXKern(LFRicBuiltIn): ''' Converts integer-valued field elements to real-valued field elements using the Fortran intrinsic `REAL` function, `Y = REAL(X, kind=r_<prec>)`. Here `Y` is a real-valued field of precision `r_<prec>` and `X` is the integer-valued field being converted. ''' _datatype = "real" _case_name = "int_to_real_X"
[docs] @classmethod def metadata(cls): '''Returns the kernel metadata describing this built-in. :returns: kernel metadata describing this built-in. :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata` ''' return cls._builtin_metadata([ FieldArgMetadata("gh_real", "gh_write", "any_space_1"), FieldArgMetadata("gh_integer", "gh_read", "any_space_1")])
def __str__(self): return (f"Built-in: {self._case_name} (convert an integer-valued " f"to a real-valued field)")
[docs] def lower_to_language_level(self) -> Node: ''' Lowers this LFRic-specific built-in kernel to language-level PSyIR. This BuiltIn node is replaced by an Assignment node. :returns: the lowered version of this node. ''' super().lower_to_language_level() # Get indexed references for each of the field (proxy) arguments. arg_refs = self.get_indexed_field_argument_references() # Create the PSyIR for the kernel: # proxy0%data(df) = REAL(proxy1%data, kind=r_<prec>) lhs = arg_refs[0] rhs = IntrinsicCall.create( IntrinsicCall.Intrinsic.REAL, [arg_refs[1], ("kind", arg_refs[0].datatype.precision.copy())]) # Create assignment and replace node return self._replace_with_assignment(lhs, rhs)
# The built-in operations that we support for this API. The meta-data # describing these kernels is in lfric_builtins_mod.f90. This dictionary # can only be defined after all of the necessary 'class' statements have # been executed (happens when this module is imported into another). #: Built-ins for real-valued fields REAL_BUILTIN_MAP_CAPITALISED = { # Adding (scaled) real fields "X_plus_Y": LFRicXPlusYKern, "inc_X_plus_Y": LFRicIncXPlusYKern, "a_plus_X": LFRicAPlusXKern, "inc_a_plus_X": LFRicIncAPlusXKern, "aX_plus_Y": LFRicAXPlusYKern, "inc_aX_plus_Y": LFRicIncAXPlusYKern, "inc_X_plus_bY": LFRicIncXPlusBYKern, "aX_plus_bY": LFRicAXPlusBYKern, "inc_aX_plus_bY": LFRicIncAXPlusBYKern, "aX_plus_aY": LFRicAXPlusAYKern, # Subtracting (scaled) real fields "X_minus_Y": LFRicXMinusYKern, "inc_X_minus_Y": LFRicIncXMinusYKern, "a_minus_X": LFRicAMinusXKern, "inc_a_minus_X": LFRicIncAMinusXKern, "X_minus_a": LFRicXMinusAKern, "inc_X_minus_a": LFRicIncXMinusAKern, "aX_minus_Y": LFRicAXMinusYKern, "X_minus_bY": LFRicXMinusBYKern, "inc_X_minus_bY": LFRicIncXMinusBYKern, "aX_minus_bY": LFRicAXMinusBYKern, # Multiplying (scaled) real fields "X_times_Y": LFRicXTimesYKern, "inc_X_times_Y": LFRicIncXTimesYKern, "inc_aX_times_Y": LFRicIncAXTimesYKern, # Multiplying real fields by a real scalar (scaling fields) "a_times_X": LFRicATimesXKern, "inc_a_times_X": LFRicIncATimesXKern, # Dividing real fields "X_divideby_Y": LFRicXDividebyYKern, "inc_X_divideby_Y": LFRicIncXDividebyYKern, "X_divideby_a": LFRicXDividebyAKern, "inc_X_divideby_a": LFRicIncXDividebyAKern, # Dividing a real scalar by elements of a real field # (inverse scaling of fields) "a_divideby_X": LFRicADividebyXKern, "inc_a_divideby_X": LFRicIncADividebyXKern, # Raising a real field to a scalar "inc_X_powreal_a": LFRicIncXPowrealAKern, "inc_X_powint_n": LFRicIncXPowintNKern, # Setting real field elements to scalar or other # real field's values "setval_c": LFRicSetvalCKern, "setval_X": LFRicSetvalXKern, "setval_random": LFRicSetvalRandomKern, # Inner product of real fields "X_innerproduct_Y": LFRicXInnerproductYKern, "X_innerproduct_X": LFRicXInnerproductXKern, # Sum values of a real field "sum_X": LFRicSumXKern, # Sign of real field elements applied to a scalar value "sign_X": LFRicSignXKern, # Maximum of a real scalar value and real field elements "max_aX": LFRicMaxAXKern, "inc_max_aX": LFRicIncMaxAXKern, # Minimum of a real scalar value and real field elements "min_aX": LFRicMinAXKern, "inc_min_aX": LFRicIncMinAXKern, # Minimum and maximum values contained in a field "minval_X": LFRicMinvalXKern, "maxval_X": LFRicMaxvalXKern, # Converting real to integer field elements "real_to_int_X": LFRicRealToIntXKern, # Converting real to real field elements "real_to_real_X": LFRicRealToRealXKern} #: Built-ins for integer-valued fields INT_BUILTIN_MAP_CAPITALISED = { # Adding integer fields "int_X_plus_Y": LFRicIntXPlusYKern, "int_inc_X_plus_Y": LFRicIntIncXPlusYKern, "int_a_plus_X": LFRicIntAPlusXKern, "int_inc_a_plus_X": LFRicIntIncAPlusXKern, # Subtracting integer fields "int_X_minus_Y": LFRicIntXMinusYKern, "int_inc_X_minus_Y": LFRicIntIncXMinusYKern, "int_a_minus_X": LFRicIntAMinusXKern, "int_inc_a_minus_X": LFRicIntIncAMinusXKern, "int_X_minus_a": LFRicIntXMinusAKern, "int_inc_X_minus_a": LFRicIntIncXMinusAKern, # Multiplying (scaled) real fields "int_X_times_Y": LFRicIntXTimesYKern, "int_inc_X_times_Y": LFRicIntIncXTimesYKern, # Multiplying integer fields by an integer scalar (scaling fields) "int_a_times_X": LFRicIntATimesXKern, "int_inc_a_times_X": LFRicIntIncATimesXKern, # Setting an integer field elements to an integer scalar # or other integer field's values "int_setval_c": LFRicIntSetvalCKern, "int_setval_X": LFRicIntSetvalXKern, # Sign of integer field elements applied to a scalar value "int_sign_X": LFRicIntSignXKern, # Maximum of an integer scalar value and integer field elements "int_max_aX": LFRicIntMaxAXKern, "int_inc_max_aX": LFRicIntIncMaxAXKern, # Minimum of an integer scalar value and integer field elements "int_min_aX": LFRicIntMinAXKern, "int_inc_min_aX": LFRicIntIncMinAXKern, # Converting integer to real field elements "int_to_real_X": LFRicIntToRealXKern} #: Built-in map dictionary for all built-ins BUILTIN_MAP_CAPITALISED = REAL_BUILTIN_MAP_CAPITALISED BUILTIN_MAP_CAPITALISED.update(INT_BUILTIN_MAP_CAPITALISED) #: Built-in map dictionary in lowercase keys for invoke generation and #: comparison purposes. This does not enforce case sensitivity to Fortran #: built-in names. BUILTIN_MAP = get_lowercase_builtin_map(BUILTIN_MAP_CAPITALISED) # For AutoAPI documentation generation. __all__ = ['LFRicBuiltInCallFactory', 'LFRicBuiltIn', 'LFRicXPlusYKern', 'LFRicIncXPlusYKern', 'LFRicAPlusXKern', 'LFRicIncAPlusXKern', 'LFRicAXPlusYKern', 'LFRicIncAXPlusYKern', 'LFRicIncXPlusBYKern', 'LFRicAXPlusBYKern', 'LFRicIncAXPlusBYKern', 'LFRicAXPlusAYKern', 'LFRicXMinusYKern', 'LFRicIncXMinusYKern', 'LFRicAMinusXKern', 'LFRicIncAMinusXKern', 'LFRicXMinusAKern', 'LFRicIncXMinusAKern', 'LFRicAXMinusYKern', 'LFRicXMinusBYKern', 'LFRicIncXMinusBYKern', 'LFRicAXMinusBYKern', 'LFRicXTimesYKern', 'LFRicIncXTimesYKern', 'LFRicIncAXTimesYKern', 'LFRicATimesXKern', 'LFRicIncATimesXKern', 'LFRicXDividebyYKern', 'LFRicIncXDividebyYKern', 'LFRicXDividebyAKern', 'LFRicIncXDividebyAKern', 'LFRicADividebyXKern', 'LFRicIncADividebyXKern', 'LFRicIncXPowrealAKern', 'LFRicIncXPowintNKern', 'LFRicSetvalCKern', 'LFRicSetvalXKern', 'LFRicSetvalRandomKern', 'LFRicXInnerproductYKern', 'LFRicXInnerproductXKern', 'LFRicSumXKern', 'LFRicSignXKern', 'LFRicMaxAXKern', 'LFRicIncMaxAXKern', 'LFRicMinAXKern', 'LFRicIncMinAXKern', 'LFRicRealToIntXKern', 'LFRicRealToRealXKern', 'LFRicIntXPlusYKern', 'LFRicIntIncXPlusYKern', 'LFRicIntAPlusXKern', 'LFRicIntIncAPlusXKern', 'LFRicIntXMinusYKern', 'LFRicIntIncXMinusYKern', 'LFRicIntAMinusXKern', 'LFRicIntIncAMinusXKern', 'LFRicIntXMinusAKern', 'LFRicIntIncXMinusAKern', 'LFRicIntXTimesYKern', 'LFRicIntIncXTimesYKern', 'LFRicIntATimesXKern', 'LFRicIntIncATimesXKern', 'LFRicIntSetvalCKern', 'LFRicIntSetvalXKern', 'LFRicIntSignXKern', 'LFRicIntMaxAXKern', 'LFRicIntIncMaxAXKern', 'LFRicIntMinAXKern', 'LFRicIntIncMinAXKern', 'LFRicIntToRealXKern']