Reference Guide  2.5.0
lfric_builtins.py
1 # -----------------------------------------------------------------------------
2 # BSD 3-Clause License
3 #
4 # Copyright (c) 2017-2024, Science and Technology Facilities Council.
5 # All rights reserved.
6 #
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions are met:
9 #
10 # * Redistributions of source code must retain the above copyright notice, this
11 # list of conditions and the following disclaimer.
12 #
13 # * Redistributions in binary form must reproduce the above copyright notice,
14 # this list of conditions and the following disclaimer in the documentation
15 # and/or other materials provided with the distribution.
16 #
17 # * Neither the name of the copyright holder nor the names of its
18 # contributors may be used to endorse or promote products derived from
19 # this software without specific prior written permission.
20 #
21 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 # POSSIBILITY OF SUCH DAMAGE.
33 # -----------------------------------------------------------------------------
34 # Author A. R. Porter, STFC Daresbury Lab
35 # Modified by I. Kavcic, L. Turner and O. Brunt, Met Office
36 # Modified by J. Henrichs, Bureau of Meteorology
37 # Modified by R. W. Ford, N. Nobre and S. Siso, STFC Daresbury Lab
38 
39 ''' This module implements the support for 'built-in' operations in the
40  PSyclone LFRic (Dynamo 0.3) API. Each supported built-in is implemented
41  as a different Python class, all inheriting from the LFRicBuiltIn class.
42  The LFRicBuiltInCallFactory creates the Python object required for
43  a given built-in call. '''
44 
45 # pylint: disable=too-many-lines
46 import abc
47 
48 from psyclone.core import AccessType, Signature, VariablesAccessInfo
49 from psyclone.domain.lfric import LFRicConstants
50 from psyclone.domain.lfric.kernel import (
51  LFRicKernelMetadata, FieldArgMetadata, ScalarArgMetadata,
52  FieldVectorArgMetadata)
53 from psyclone.errors import InternalError
54 from psyclone.parse.utils import ParseError
55 from psyclone.psyGen import BuiltIn
56 from psyclone.psyir.nodes import (ArrayReference, Assignment, BinaryOperation,
57  Reference, IntrinsicCall)
58 from psyclone.utils import a_or_an
59 
60 # The name of the file containing the meta-data describing the
61 # built-in operations for this API
62 BUILTIN_DEFINITIONS_FILE = "lfric_builtins_mod.f90"
63 
64 
65 # Function to return the built-in operations that we support for this API.
66 # The meta-data describing these kernels is in lfric_builtins_mod.f90.
67 # The built-in operations F90 capitalised names are dictionary keys and need
68 # to be converted to lower case for invoke-generation purpose.
69 def get_lowercase_builtin_map(builtin_map_capitalised_dict):
70  '''
71  Convert the names of the supported built-in operations to lowercase
72  for comparison and invoke-generation purpose.
73 
74  :param builtin_map_capitalised_dict: a dictionary of built-in names.
75  :type builtin_map_capitalised_dict: dict of str
76 
77  :returns: a dictionary of lowercase Fortran built-in names as keys \
78  and case-sensitive Python built-in names as values.
79  :rtype: dict of str
80 
81  '''
82  builtin_map_dict = {}
83  for fortran_name in builtin_map_capitalised_dict:
84  python_name = builtin_map_capitalised_dict[fortran_name]
85  builtin_map_dict[fortran_name.lower()] = python_name
86  return builtin_map_dict
87 
88 
90  '''Creates the necessary framework for a call to an LFRic built-in,
91  This consists of the operation itself and the loop over unique
92  DoFs.
93 
94  '''
95 
96  def __str__(self):
97  return "Factory for a call to an LFRic built-in."
98 
99  @staticmethod
100  def create(call, parent=None):
101  '''
102  Create the objects needed for a call to the built-in described in
103  the call (BuiltInCall) object.
104 
105  :param call: details of the call to this built-in in the \
106  Algorithm layer.
107  :type call: :py:class:`psyclone.parse.algorithm.BuiltInCall`
108  :param parent: the schedule instance to which the built-in call \
109  belongs.
110  :type parent: :py:class:`psyclone.dynamo0p3.DynInvokeSchedule`
111 
112  :raises ParseError: if the name of the function being called is \
113  not a recognised built-in.
114  :raises InternalError: if the built-in does not iterate over DoFs.
115 
116  '''
117  if call.func_name not in BUILTIN_MAP:
118  raise ParseError(
119  f"Unrecognised built-in call in LFRic API: found "
120  f"'{call.func_name}' but expected one of "
121  f"{list(BUILTIN_MAP_CAPITALISED.keys())}.")
122 
123  # Use our dictionary to get the correct Python object for
124  # this built-in.
125  builtin = BUILTIN_MAP[call.func_name]()
126 
127  # Create the loop over the appropriate entity.
128  # Avoid circular import
129  # pylint: disable=import-outside-toplevel
130  from psyclone.domain.lfric import LFRicLoop
131 
132  if call.ktype.iterates_over == "dof":
133  loop_type = "dof"
134  else:
135  raise InternalError(
136  f"An LFRic built-in must iterate over DoFs but kernel "
137  f"'{call.func_name}' iterates over "
138  f"'{call.ktype.iterates_over}'")
139  dofloop = LFRicLoop(parent=parent, loop_type=loop_type)
140 
141  # Use the call object (created by the parser) to set-up the state
142  # of the infrastructure kernel
143  builtin.load(call, parent=dofloop.loop_body)
144 
145  # Set-up its state
146  dofloop.load(builtin)
147 
148  # As it is the innermost loop it has the kernel as a loop_body
149  # child.
150  dofloop.loop_body.addchild(builtin)
151 
152  # Return the outermost loop
153  return dofloop
154 
155 
156 class LFRicBuiltIn(BuiltIn, metaclass=abc.ABCMeta):
157  '''Abstract base class for a node representing a call to an LFRic
158  built-in.
159 
160  :raises NotImplementedError: if a subclass of this abstract class \
161  does not set the value of '_datatype'.
162 
163  '''
164  _case_name = None
165  _datatype = None
166 
167  def __init__(self):
168  # Builtins do not accept quadrature
169  self.qr_rulesqr_rules = {}
170  # Builtins cannot request mesh properties
171  self.meshmesh = None
172  self._idx_name_idx_name = None
173  if not self._datatype_datatype:
174  raise NotImplementedError(
175  "An LFRicBuiltIn should be overridden by a subclass that "
176  "sets the value of '_datatype', but '_datatype' is not set.")
177  super().__init__()
178 
179  @staticmethod
180  @abc.abstractmethod
181  def metadata():
182  '''Must be overridden by subclass.'''
183 
184  @classmethod
185  def _builtin_metadata(cls, meta_args):
186  '''Utility to take 'meta_args' metadata and return LFRic kernel
187  metadata for a built-in. Assumes the metadata describes a
188  built-in kernel that operates on a DoF and that the naming
189  protocol uses the name of the metadata type and adds '_code'
190  to it for the name of the subroutine.
191 
192  :param meta_args: a list of 'meta_args' metadata.
193  :type meta_args: List[subclass of \
194  :py:class:`psyclone.domain.lfric.kernel.CommonArgMetadata`]
195 
196  :returns: LFRic kernel metadata for this built-in.
197  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
198 
199  '''
200  return LFRicKernelMetadata(
201  meta_args=meta_args,
202  operates_on="dof",
203  procedure_name=f"{cls._case_name}_code",
204  name=cls._case_name_case_name)
205 
206  def __str__(self):
207  metadata = self.metadatametadata()
208  plural = ""
209  # Builtins are currenty limited to fields and scalars but add
210  # in a check for field-vectors as well for future proofing.
211  if len(metadata.meta_args_get([
212  FieldArgMetadata, FieldVectorArgMetadata])) > 1:
213  plural = "s"
214  return (f"Built-in: {self._case_name} ("
215  f"{self._datatype}-valued field{plural})")
216 
217  def reference_accesses(self, var_accesses):
218  '''Get all variable access information from this node. The assigned-to
219  variable will be set to 'WRITE'.
220 
221  :param var_accesses: VariablesAccessInfo instance that stores the \
222  information about variable accesses.
223  :type var_accesses: \
224  :py:class:`psyclone.core.VariablesAccessInfo`
225 
226  :raises InternalError: if an unsupported argument type is encountered.
227 
228  '''
229  table = self.scope.symbol_table
230  # Collect all write access in a separate object, so they can be added
231  # after all read access (which must happen before something is written)
232  written = VariablesAccessInfo()
233  suffix_map = LFRicConstants().ARG_TYPE_SUFFIX_MAPPING
234 
235  for arg in self.argsargs:
236  if arg.form in ["variable", "indexed_variable"]:
237  if arg.is_field:
238  sym = table.lookup_with_tag(
239  f"{arg.name}:{suffix_map[arg.argument_type]}")
240  name = sym.name
241  elif arg.is_scalar:
242  name = arg.declaration_name
243  else:
244  raise InternalError(
245  f"LFRicBuiltin.reference_accesses only supports field "
246  f"and scalar arguments but got '{arg.name}' of type "
247  f"'{arg.argument_type}'")
248  if arg.access == AccessType.WRITE:
249  written.add_access(Signature(name), arg.access, self)
250  else:
251  var_accesses.add_access(Signature(name), arg.access, self)
252  # Now merge the write access to the end of all other accesses:
253  var_accesses.merge(written)
254  # Forward location pointer to next index, since this built-in kernel
255  # finishes a statement
256  var_accesses.next_location()
257 
258  def load(self, call, parent=None):
259  '''
260  Populate the state of this object using the supplied call object.
261 
262  :param call: The BuiltIn object from which to extract information \
263  about this built-in call.
264  :type call: :py:class:`psyclone.parse.algorithm.BuiltInCall`
265  :param parent: The parent node of the kernel call in the PSyIR \
266  we are constructing. This will be a loop.
267  :type parent: :py:class:`psyclone.domain.lfric.LFRicLoop`
268 
269  '''
270  # Avoid circular import
271  # pylint: disable=import-outside-toplevel
272  from psyclone.dynamo0p3 import FSDescriptors, DynKernelArguments
273  BuiltIn.load(self, call, DynKernelArguments, parent)
274  self.arg_descriptorsarg_descriptorsarg_descriptorsarg_descriptors = call.ktype.arg_descriptors
275  self._func_descriptors_func_descriptors_func_descriptors = call.ktype.func_descriptors
276  self._fs_descriptors_fs_descriptors_fs_descriptors = FSDescriptors(call.ktype.func_descriptors)
277  self._idx_name_idx_name = self.get_dof_loop_index_symbolget_dof_loop_index_symbol().name
278  # Check that this built-in kernel is valid
279  self._validate_validate()
280 
281  def _validate(self):
282  '''
283  Check that this built-in conforms to the LFRic API.
284 
285  :raises ParseError: if a built-in call does not iterate over DoFs.
286  :raises ParseError: if an argument to a built-in kernel is not \
287  one of valid argument types.
288  :raises ParseError: if an argument to a built-in kernel has \
289  an invalid data type.
290  :raises ParseError: if a built-in kernel writes to more than \
291  one argument.
292  :raises ParseError: if a built-in kernel does not have at least \
293  one field argument.
294  :raises ParseError: if all field arguments are not on the same space.
295  :raises ParseError: if all field arguments of a non-conversion \
296  built-in do not have the same data type.
297 
298  '''
299  const = LFRicConstants()
300  # Check that our assumption that we're looping over DoFs is valid
301  if self.iterates_overiterates_over not in const.BUILTIN_ITERATION_SPACES:
302  raise ParseError(
303  f"In the LFRic API built-in calls must operate on one of "
304  f"{const.BUILTIN_ITERATION_SPACES} but found "
305  f"'{self.iterates_over}' for {self}.")
306  # Check write count, field arguments and spaces
307  write_count = 0 # Only one argument must be written to
308  field_count = 0 # We must have one or more fields as arguments
309  spaces = set() # All field arguments must be on the same space
310  # Field data types must be the same except for the conversion built-ins
311  data_types = set()
312  for arg in self.arg_descriptorsarg_descriptorsarg_descriptorsarg_descriptors:
313  # Check valid argument types
314  if arg.argument_type not in const.VALID_BUILTIN_ARG_TYPES:
315  raise ParseError(
316  f"In the LFRic API an argument to a built-in kernel "
317  f"must be one of {const.VALID_BUILTIN_ARG_TYPES} but "
318  f"kernel '{self.name}' has an argument of type "
319  f"'{arg.argument_type}'.")
320  # Check valid data types
321  if arg.data_type not in const.VALID_BUILTIN_DATA_TYPES:
322  raise ParseError(
323  f"In the LFRic API an argument to a built-in kernel "
324  f"must have one of {const.VALID_BUILTIN_DATA_TYPES} as "
325  f"a data type but kernel '{self.name}' has an argument "
326  f"of data type '{arg.data_type}'.")
327  # Built-ins update fields DoF by DoF and therefore can have
328  # WRITE/READWRITE access
329  if arg.access in [AccessType.WRITE, AccessType.SUM,
330  AccessType.READWRITE]:
331  write_count += 1
332  if arg.argument_type in const.VALID_FIELD_NAMES:
333  field_count += 1
334  spaces.add(arg.function_space)
335  data_types.add(arg.data_type)
336 
337  if write_count != 1:
338  raise ParseError(f"A built-in kernel in the LFRic API must "
339  f"have one and only one argument that is "
340  f"written to but found {write_count} for "
341  f"kernel '{self.name}'.")
342  if field_count == 0:
343  raise ParseError(f"A built-in kernel in the LFRic API must have "
344  f"at least one field as an argument but "
345  f"kernel '{self.name}' has none.")
346  if len(spaces) != 1:
347  spaces_str = [str(x) for x in sorted(spaces)]
348  raise ParseError(
349  f"All field arguments to a built-in in the LFRic API "
350  f"must be on the same space. However, found spaces "
351  f"{spaces_str} for arguments to '{self.name}'")
352 
353  conversion_builtins = ["real_to_int_X",
354  "real_to_real_X",
355  "int_to_real_X"]
356  conversion_builtins_lower = [x.lower() for x in conversion_builtins]
357  if len(data_types) != 1 and self.namenamename not in conversion_builtins_lower:
358  data_types_str = [str(x) for x in sorted(data_types)]
359  raise ParseError(
360  f"In the LFRic API only the data type conversion built-ins "
361  f"{conversion_builtins} are allowed to have field arguments of"
362  f" different data types. However, found different data types "
363  f"{data_types_str} for field arguments to '{self.name}'.")
364 
365  @property
366  def undf_name(self):
367  '''
368  Dynamically looks up the name of the 'undf' variable for the
369  space that this kernel updates.
370 
371  :returns: the name of the undf variable.
372  :rtype: str
373 
374  '''
375  field = self._arguments_arguments.iteration_space_arg()
376  return field.function_space.undf_name
377 
378  @property
379  def qr_required(self):
380  '''
381  Built-ins do not currently require quadrature.
382 
383  :returns: False
384  :rtype: bool
385 
386  '''
387  return False
388 
389  @property
390  def reference_element(self):
391  '''
392  Built-ins do not require reference-element properties.
393 
394  :returns: None
395  :rtype: NoneType
396 
397  '''
398  return None
399 
400  @property
401  def cma_operation(self):
402  '''
403  Built-ins do not perform operations with Column-Matrix-Assembly
404  operators.
405 
406  :returns: None
407  :rtype: NoneType
408 
409  '''
410  return None
411 
412  @property
413  def is_intergrid(self):
414  '''
415  We don't have any inter-grid built-ins.
416 
417  :returns: False
418  :rtype: bool
419 
420  '''
421  return False
422 
423  @property
424  def fs_descriptors(self):
425  '''
426  :returns: a list of function space descriptor objects which \
427  contain information about the function spaces.
428  :rtype: list of :py:class:`psyclone.dynamo0p3.FSDescriptor`
429 
430  '''
431  return self._fs_descriptors_fs_descriptors_fs_descriptors
432 
434  '''
435  Finds or creates the symbol representing the index in any loops
436  over DoFs.
437 
438  :returns: symbol representing the DoF loop index.
439  :rtype: :py:class:`psyclone.psyir.symbols.DataSymbol`
440 
441  '''
442  table = self.scope.symbol_table
443  # The symbol representing the loop index is created in the LFRicLoop
444  # constructor.
445  return table.find_or_create_integer_symbol(
446  "df", tag="dof_loop_idx")
447 
449  '''
450  Creates a DoF-indexed StructureReference for each of the field
451  arguments to this Built-In kernel. e.g. if the kernel has a field
452  argument named 'fld1' then this routine will create an
453  ArrayReference for 'fld1_data(df)' where 'df' is the DoF-loop
454  variable and 'fld1_data' is the pointer to the data array within
455  the fld1 object.
456 
457  :returns: a reference to the 'df'th element of each kernel argument
458  that is a field.
459  :rtype: List[:py:class:`psyclone.psyir.nodes.ArrayReference`]
460 
461  '''
462  table = self.scope.symbol_table
463  idx_sym = self.get_dof_loop_index_symbolget_dof_loop_index_symbol()
464  suffixes = LFRicConstants().ARG_TYPE_SUFFIX_MAPPING
465 
466  refs = []
467  for arg in self._arguments_arguments.args:
468  if not arg.is_field:
469  continue
470  sym = table.lookup_with_tag(
471  f"{arg.name}:{suffixes[arg.argument_type]}")
472  refs.append(ArrayReference.create(sym, [Reference(idx_sym)]))
473  return refs
474 
476  '''
477  Finds or creates either a Reference (for a symbol) or PSyIR (for a
478  literal expression) for any scalar arguments to this Built-In kernel.
479 
480  :returns: a Reference or PSyIR expression for each scalar kernel
481  argument.
482  :rtype: list of subclasses of `:py:class:`psyclone.psyir.nodes.Node`
483 
484  '''
485  return [arg.psyir_expression() for arg in self._arguments_arguments.args
486  if arg.is_scalar]
487 
488  def _replace_with_assignment(self, lhs, rhs):
489  '''
490  Creates an assignment from the left- and right-hand-side nodes, then
491  replaces this Builtin with the newly-created Assignment node.
492 
493  :param lhs: The left-hand side of the assignment to be created.
494  :type lhs: :py:class:`psyclone.psyir.nodes.ArrayReference`
495  :param rhs: The right-hand side of the assignment to be created.
496  :type rhs: :py:class:`psyclone.psyir.nodes.DataNode`
497 
498  :returns: the new Assignment node.
499  :rtype: :py:class:`psyclone.psyir.nodes.Assignment`
500 
501  '''
502  assign = Assignment.create(lhs, rhs)
503  # Add a preceding comment to the Assignment
504  assign.preceding_comment = str(self)
505  self.replace_with(assign)
506 
507  return assign
508 
509 
510 # ******************************************************************* #
511 # ************** Built-ins for real-valued fields ******************* #
512 # ******************************************************************* #
513 
514 # ------------------------------------------------------------------- #
515 # ============== Adding (scaled) real fields ======================== #
516 # ------------------------------------------------------------------- #
517 
518 
520  ''' Add one, real-valued, field to another and return the result as
521  a third, real-valued, field.
522 
523  '''
524  _case_name = "X_plus_Y"
525  _datatype = "real"
526 
527  @classmethod
528  def metadata(cls):
529  '''Returns the kernel metadata describing this built-in. Implemented in
530  a datatype-independent way to allow for re-use.
531 
532  :returns: kernel metadata describing this built-in.
533  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
534 
535  '''
536  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
537  metadata = cls._builtin_metadata_builtin_metadata([
538  FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"),
539  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1"),
540  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
541  metadata.validate()
542  return metadata
543 
544  def __str__(self):
545  return (f"Built-in: {self._case_name} (add "
546  f"{self._datatype}-valued fields)")
547 
549  '''
550  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
551  This Built-In node is replaced by an Assignment node.
552 
553  :returns: the lowered version of this node.
554  :rtype: :py:class:`psyclone.psyir.node.Node`
555 
556  '''
557  # Get indexed references for each of the field (proxy) arguments.
558  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
559 
560  # Create the PSyIR for the kernel:
561  # proxy0%data(df) = proxy1%data(df) + proxy2%data(df)
562  lhs = arg_refs[0]
563  rhs = BinaryOperation.create(BinaryOperation.Operator.ADD,
564  arg_refs[1], arg_refs[2])
565 
566  # Create assignment and replace node
567  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
568 
569 
571  ''' Add the second, real-valued, field to the first field and return it.
572 
573  '''
574  _case_name = "inc_X_plus_Y"
575  _datatype = "real"
576 
577  @classmethod
578  def metadata(cls):
579  '''Returns the kernel metadata describing this built-in.
580 
581  :returns: kernel metadata describing this built-in.
582  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
583 
584  '''
585  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
586  return cls._builtin_metadata_builtin_metadata([
587  FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1"),
588  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
589 
590  def __str__(self):
591  return (f"Built-in: {self._case_name} (increment "
592  f"{a_or_an(self._datatype)} {self._datatype}-valued field)")
593 
595  '''
596  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
597  This BuiltIn node is replaced by an Assignment node.
598 
599  :returns: the lowered version of this node.
600  :rtype: :py:class:`psyclone.psyir.node.Node`
601 
602  '''
603  # Get indexed refs for both of the field (proxy) arguments.
604  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
605 
606  # Create the PSyIR for the kernel:
607  # proxy0%data(df) = proxy0%data(df) + proxy1%data(df)
608  lhs = arg_refs[0]
609  rhs = BinaryOperation.create(BinaryOperation.Operator.ADD,
610  lhs.copy(), arg_refs[1])
611 
612  # Create assignment and replace node
613  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
614 
615 
617  ''' `Y = a + X` where `a` is a real scalar and `X` and `Y` are
618  real-valued fields (DoF-wise addition of a scalar value).
619 
620  '''
621  _case_name = "a_plus_X"
622  _datatype = "real"
623 
624  @classmethod
625  def metadata(cls):
626  '''Returns the kernel metadata describing this built-in.
627 
628  :returns: kernel metadata describing this built-in.
629  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
630 
631  '''
632  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
633  return cls._builtin_metadata_builtin_metadata([
634  FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"),
635  ScalarArgMetadata(gh_datatype, "gh_read"),
636  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
637 
639  '''
640  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
641  This BuiltIn node is replaced by an Assignment node.
642 
643  :returns: the lowered version of this node.
644  :rtype: :py:class:`psyclone.psyir.node.Node`
645 
646  '''
647  # Get indexed references for each of the field (proxy) arguments.
648  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
649  # Get a reference for the kernel scalar argument.
650  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
651 
652  # Create the PSyIR for the kernel:
653  # proxy0%data(df) = ascalar + proxy1%data(df)
654  lhs = arg_refs[0]
655  rhs = BinaryOperation.create(BinaryOperation.Operator.ADD,
656  scalar_args[0], arg_refs[1])
657 
658  # Create assignment and replace node
659  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
660 
661 
663  ''' `X = a + X` where `a` is a real scalar and `X` is a real-valued
664  field (DoF-wise addition of a scalar value).
665 
666  '''
667  _case_name = "inc_a_plus_X"
668  _datatype = "real"
669 
670  @classmethod
671  def metadata(cls):
672  '''Returns the kernel metadata describing this built-in.
673 
674  :returns: kernel metadata describing this built-in.
675  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
676 
677  '''
678  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
679  return cls._builtin_metadata_builtin_metadata([
680  ScalarArgMetadata(gh_datatype, "gh_read"),
681  FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1")])
682 
684  '''
685  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
686  This BuiltIn node is replaced by an Assignment node.
687 
688  :returns: the lowered version of this node.
689  :rtype: :py:class:`psyclone.psyir.node.Node`
690 
691  '''
692  # Get indexed references for each of the field (proxy) arguments.
693  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
694  # Get a reference for the kernel scalar argument.
695  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
696 
697  # Create the PSyIR for the kernel:
698  # proxy0%data(df) = ascalar + proxy0%data(df)
699  lhs = arg_refs[0]
700  rhs = BinaryOperation.create(BinaryOperation.Operator.ADD,
701  scalar_args[0], lhs.copy())
702 
703  # Create assignment and replace node
704  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
705 
706 
708  ''' `Z = a*X + Y` where `a` is a real scalar and `Z`, `X` and
709  `Y` are real-valued fields.
710 
711  '''
712  _case_name = "aX_plus_Y"
713  _datatype = "real"
714 
715  @classmethod
716  def metadata(cls):
717  '''Returns the kernel metadata describing this built-in.
718 
719  :returns: kernel metadata describing this built-in.
720  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
721 
722  '''
723  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
724  return cls._builtin_metadata_builtin_metadata([
725  FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"),
726  ScalarArgMetadata(gh_datatype, "gh_read"),
727  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1"),
728  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
729 
731  '''
732  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
733  This BuiltIn node is replaced by an Assignment node.
734 
735  :returns: the lowered version of this node.
736  :rtype: :py:class:`psyclone.psyir.node.Node`
737 
738  '''
739  # Get indexed references for each of the field (proxy) arguments.
740  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
741  # Get a reference for the kernel scalar argument.
742  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
743 
744  # Create the PSyIR for the kernel:
745  # proxy0%data(df) = ascalar * proxy1%data(df) + proxy2%data(df)
746  lhs = arg_refs[0]
747  mult_op = BinaryOperation.create(BinaryOperation.Operator.MUL,
748  scalar_args[0], arg_refs[1])
749  rhs = BinaryOperation.create(BinaryOperation.Operator.ADD,
750  mult_op, arg_refs[2])
751 
752  # Create assignment and replace node
753  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
754 
755 
757  ''' `X = a*X + Y` where `a` is a real scalar and `X` and `Y` are
758  real-valued fields.
759 
760  '''
761  _case_name = "inc_aX_plus_Y"
762  _datatype = "real"
763 
764  @classmethod
765  def metadata(cls):
766  '''Returns the kernel metadata describing this built-in.
767 
768  :returns: kernel metadata describing this built-in.
769  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
770 
771  '''
772  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
773  return cls._builtin_metadata_builtin_metadata([
774  ScalarArgMetadata(gh_datatype, "gh_read"),
775  FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1"),
776  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
777 
779  '''
780  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
781  This BuiltIn node is replaced by an Assignment node.
782 
783  :returns: the lowered version of this node.
784  :rtype: :py:class:`psyclone.psyir.node.Node`
785 
786  '''
787  # Get indexed references for each of the field (proxy) arguments.
788  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
789  # Get a reference for the kernel scalar argument.
790  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
791 
792  # Create the PSyIR for the kernel:
793  # proxy0%data(df) = ascalar * proxy0%data(df) + proxy1%data(df)
794  lhs = arg_refs[0]
795  mult_op = BinaryOperation.create(BinaryOperation.Operator.MUL,
796  scalar_args[0], lhs.copy())
797  rhs = BinaryOperation.create(BinaryOperation.Operator.ADD,
798  mult_op, arg_refs[1])
799 
800  # Create assignment and replace node
801  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
802 
803 
805  ''' `X = X + b*Y` where `b` is a real scalar and `X` and `Y` are
806  real-valued fields.
807 
808  '''
809  _case_name = "inc_X_plus_bY"
810  _datatype = "real"
811 
812  @classmethod
813  def metadata(cls):
814  '''Returns the kernel metadata describing this built-in.
815 
816  :returns: kernel metadata describing this built-in.
817  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
818 
819  '''
820  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
821  return cls._builtin_metadata_builtin_metadata([
822  FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1"),
823  ScalarArgMetadata(gh_datatype, "gh_read"),
824  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
825 
827  '''
828  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
829  This BuiltIn node is replaced by an Assignment node.
830 
831  :returns: the lowered version of this node.
832  :rtype: :py:class:`psyclone.psyir.node.Node`
833 
834  '''
835  # Get indexed references for each of the field (proxy) arguments.
836  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
837  # Get a reference for the kernel scalar argument.
838  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
839 
840  # Create the PSyIR for the kernel:
841  # proxy0%data(df) = proxy0%data(df) + bscalar * proxy1%data(df)
842  lhs = arg_refs[0]
843  mult_op = BinaryOperation.create(BinaryOperation.Operator.MUL,
844  scalar_args[0], arg_refs[1])
845  rhs = BinaryOperation.create(BinaryOperation.Operator.ADD,
846  lhs.copy(), mult_op)
847 
848  # Create assignment and replace node
849  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
850 
851 
853  ''' `Z = a*X + b*Y` where `a` and `b` are real scalars and `Z`, `X` and
854  `Y` are real-valued fields.
855 
856  '''
857  _case_name = "aX_plus_bY"
858  _datatype = "real"
859 
860  @classmethod
861  def metadata(cls):
862  '''Returns the kernel metadata describing this built-in.
863 
864  :returns: kernel metadata describing this built-in.
865  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
866 
867  '''
868  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
869  return cls._builtin_metadata_builtin_metadata([
870  FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"),
871  ScalarArgMetadata(gh_datatype, "gh_read"),
872  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1"),
873  ScalarArgMetadata(gh_datatype, "gh_read"),
874  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
875 
877  '''
878  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
879  This BuiltIn node is replaced by an Assignment node.
880 
881  :returns: the lowered version of this node.
882  :rtype: :py:class:`psyclone.psyir.node.Node`
883 
884  '''
885  # Get indexed references for each of the field (proxy) arguments.
886  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
887  # Get a reference for the kernel scalar argument.
888  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
889 
890  # Create the PSyIR for the kernel:
891  # proxy0%data(df) = ascalar * proxy1%data(df) +
892  # bscalar *proxy2%data(df)
893  lhs = arg_refs[0]
894  mult_op_a = BinaryOperation.create(BinaryOperation.Operator.MUL,
895  scalar_args[0], arg_refs[1])
896  mult_op_b = BinaryOperation.create(BinaryOperation.Operator.MUL,
897  scalar_args[1], arg_refs[2])
898  rhs = BinaryOperation.create(BinaryOperation.Operator.ADD,
899  mult_op_a, mult_op_b)
900 
901  # Create assignment and replace node
902  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
903 
904 
906  ''' `X = a*X + b*Y` where `a` and `b` are real scalars and `X` and `Y`
907  are real-valued fields.
908 
909  '''
910  _case_name = "inc_aX_plus_bY"
911  _datatype = "real"
912 
913  @classmethod
914  def metadata(cls):
915  '''Returns the kernel metadata describing this built-in.
916 
917  :returns: kernel metadata describing this built-in.
918  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
919 
920  '''
921  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
922  return cls._builtin_metadata_builtin_metadata([
923  ScalarArgMetadata(gh_datatype, "gh_read"),
924  FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1"),
925  ScalarArgMetadata(gh_datatype, "gh_read"),
926  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
927 
929  '''
930  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
931  This BuiltIn node is replaced by an Assignment node.
932 
933  :returns: the lowered version of this node.
934  :rtype: :py:class:`psyclone.psyir.node.Node`
935 
936  '''
937  # Get indexed references for each of the field (proxy) arguments.
938  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
939  # Get a reference for the kernel scalar argument.
940  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
941 
942  # Create the PSyIR for the kernel:
943  # proxy0%data(df) = ascalar * proxy0%data(df) +
944  # bscalar * proxy1%data(df)
945  lhs = arg_refs[0]
946  mult_op_a = BinaryOperation.create(BinaryOperation.Operator.MUL,
947  scalar_args[0], lhs.copy())
948  mult_op_b = BinaryOperation.create(BinaryOperation.Operator.MUL,
949  scalar_args[1], arg_refs[1])
950  rhs = BinaryOperation.create(BinaryOperation.Operator.ADD,
951  mult_op_a, mult_op_b)
952 
953  # Create assignment and replace node
954  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
955 
956 
958  ''' `Z = a*X + a*Y = a*(X + Y)` where `a` is a real scalar and `Z`,
959  `X` and `Y` are real-valued fields.
960 
961  '''
962  _case_name = "aX_plus_aY"
963  _datatype = "real"
964 
965  @classmethod
966  def metadata(cls):
967  '''Returns the kernel metadata describing this built-in.
968 
969  :returns: kernel metadata describing this built-in.
970  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
971 
972  '''
973  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
974  return cls._builtin_metadata_builtin_metadata([
975  FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"),
976  ScalarArgMetadata(gh_datatype, "gh_read"),
977  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1"),
978  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
979 
981  '''
982  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
983  This BuiltIn node is replaced by an Assignment node.
984 
985  :returns: the lowered version of this node.
986  :rtype: :py:class:`psyclone.psyir.node.Node`
987 
988  '''
989  # Get indexed references for each of the field (proxy) arguments.
990  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
991  # Get a reference for the kernel scalar argument.
992  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
993 
994  # Create the PSyIR for the kernel:
995  # proxy0%data(df) = ascalar * (proxy1%data(df) + proxy2%data(df))
996  lhs = arg_refs[0]
997  add_op = BinaryOperation.create(BinaryOperation.Operator.ADD,
998  arg_refs[1], arg_refs[2])
999  rhs = BinaryOperation.create(BinaryOperation.Operator.MUL,
1000  scalar_args[0], add_op)
1001 
1002  # Create assignment and replace node
1003  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
1004 
1005 
1006 # ------------------------------------------------------------------- #
1007 # ============== Subtracting (scaled) real fields =================== #
1008 # ------------------------------------------------------------------- #
1009 
1010 
1012  ''' Subtract one, real-valued, field from another and return the
1013  result as a third, real-valued, field.
1014 
1015  '''
1016  _case_name = "X_minus_Y"
1017  _datatype = "real"
1018 
1019  @classmethod
1020  def metadata(cls):
1021  '''Returns the kernel metadata describing this built-in.
1022 
1023  :returns: kernel metadata describing this built-in.
1024  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
1025 
1026  '''
1027  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
1028  return cls._builtin_metadata_builtin_metadata([
1029  FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"),
1030  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1"),
1031  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
1032 
1033  def __str__(self):
1034  return (f"Built-in: {self._case_name} (subtract "
1035  f"{self._datatype}-valued fields)")
1036 
1038  '''
1039  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
1040  This BuiltIn node is replaced by an Assignment node.
1041 
1042  :returns: the lowered version of this node.
1043  :rtype: :py:class:`psyclone.psyir.node.Node`
1044 
1045  '''
1046  # Get indexed references for each of the field (proxy) arguments.
1047  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
1048 
1049  # Create the PSyIR for the kernel:
1050  # proxy0%data(df) = proxy1%data(df) - proxy2%data(df)
1051  lhs = arg_refs[0]
1052  rhs = BinaryOperation.create(BinaryOperation.Operator.SUB,
1053  arg_refs[1], arg_refs[2])
1054 
1055  # Create assignment and replace node
1056  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
1057 
1058 
1060  ''' Subtract the second, real-valued, field from the first field
1061  and return it.
1062 
1063  '''
1064  _case_name = "inc_X_minus_Y"
1065  _datatype = "real"
1066 
1067  @classmethod
1068  def metadata(cls):
1069  '''Returns the kernel metadata describing this built-in.
1070 
1071  :returns: kernel metadata describing this built-in.
1072  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
1073 
1074  '''
1075  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
1076  return cls._builtin_metadata_builtin_metadata([
1077  FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1"),
1078  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
1079 
1080  def __str__(self):
1081  return (f"Built-in: {self._case_name} (decrement "
1082  f"{a_or_an(self._datatype)} {self._datatype}-valued field)")
1083 
1085  '''
1086  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
1087  This BuiltIn node is replaced by an Assignment node.
1088 
1089  :returns: the lowered version of this node.
1090  :rtype: :py:class:`psyclone.psyir.node.Node`
1091 
1092  '''
1093  # Get indexed refs for both of the field (proxy) arguments.
1094  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
1095 
1096  # Create the PSyIR for the kernel:
1097  # proxy0%data(df) = proxy0%data(df) - proxy1%data(df)
1098  lhs = arg_refs[0]
1099  rhs = BinaryOperation.create(BinaryOperation.Operator.SUB,
1100  lhs.copy(), arg_refs[1])
1101 
1102  # Create assignment and replace node
1103  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
1104 
1105 
1107  ''' `Y = a - X` where `a` is a real scalar and `X` and `Y` are real-valued
1108  fields (DoF-wise subtraction of field elements from a scalar value).
1109 
1110  '''
1111  _case_name = "a_minus_X"
1112  _datatype = "real"
1113 
1114  @classmethod
1115  def metadata(cls):
1116  '''Returns the kernel metadata describing this built-in.
1117 
1118  :returns: kernel metadata describing this built-in.
1119  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
1120 
1121  '''
1122  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
1123  return cls._builtin_metadata_builtin_metadata([
1124  FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"),
1125  ScalarArgMetadata(gh_datatype, "gh_read"),
1126  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
1127 
1129  '''
1130  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
1131  This BuiltIn node is replaced by an Assignment node.
1132 
1133  :returns: the lowered version of this node.
1134  :rtype: :py:class:`psyclone.psyir.node.Node`
1135 
1136  '''
1137  # Get indexed references for each of the field (proxy) arguments.
1138  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
1139  # Get a reference for the kernel scalar argument.
1140  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
1141 
1142  # Create the PSyIR for the kernel:
1143  # proxy0%data(df) = ascalar - proxy1%data(df)
1144  lhs = arg_refs[0]
1145  rhs = BinaryOperation.create(BinaryOperation.Operator.SUB,
1146  scalar_args[0], arg_refs[1])
1147 
1148  # Create assignment and replace node
1149  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
1150 
1151 
1153  ''' `X = a - X` where `a` is a real scalar and `X` is a real-valued
1154  field (DoF-wise subtraction of field elements from a scalar value).
1155 
1156  '''
1157  _case_name = "inc_a_minus_X"
1158  _datatype = "real"
1159 
1160  @classmethod
1161  def metadata(cls):
1162  '''Returns the kernel metadata describing this built-in.
1163 
1164  :returns: kernel metadata describing this built-in.
1165  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
1166 
1167  '''
1168  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
1169  return cls._builtin_metadata_builtin_metadata([
1170  ScalarArgMetadata(gh_datatype, "gh_read"),
1171  FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1")])
1172 
1174  '''
1175  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
1176  This BuiltIn node is replaced by an Assignment node.
1177 
1178  :returns: the lowered version of this node.
1179  :rtype: :py:class:`psyclone.psyir.node.Node`
1180 
1181  '''
1182  # Get indexed references for each of the field (proxy) arguments.
1183  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
1184  # Get a reference for the kernel scalar argument.
1185  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
1186 
1187  # Create the PSyIR for the kernel:
1188  # proxy0%data(df) = ascalar - proxy0%data(df)
1189  lhs = arg_refs[0]
1190  rhs = BinaryOperation.create(BinaryOperation.Operator.SUB,
1191  scalar_args[0], lhs.copy())
1192 
1193  # Create assignment and replace node
1194  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
1195 
1196 
1198  ''' `Y = X - a` where `a` is a real scalar and `X` and `Y` are real-valued
1199  fields (DoF-wise subtraction of a scalar value from field elements).
1200 
1201  '''
1202  _case_name = "X_minus_a"
1203  _datatype = "real"
1204 
1205  @classmethod
1206  def metadata(cls):
1207  '''Returns the kernel metadata describing this built-in.
1208 
1209  :returns: kernel metadata describing this built-in.
1210  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
1211 
1212  '''
1213  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
1214  return cls._builtin_metadata_builtin_metadata([
1215  FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"),
1216  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1"),
1217  ScalarArgMetadata(gh_datatype, "gh_read")])
1218 
1220  '''
1221  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
1222  This BuiltIn node is replaced by an Assignment node.
1223 
1224  :returns: the lowered version of this node.
1225  :rtype: :py:class:`psyclone.psyir.node.Node`
1226 
1227  '''
1228  # Get indexed references for each of the field (proxy) arguments.
1229  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
1230  # Get a reference for the kernel scalar argument.
1231  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
1232 
1233  # Create the PSyIR for the kernel:
1234  # proxy0%data(df) = proxy1%data(df) - ascalar
1235  lhs = arg_refs[0]
1236  rhs = BinaryOperation.create(BinaryOperation.Operator.SUB,
1237  arg_refs[1], scalar_args[0])
1238 
1239  # Create assignment and replace node
1240  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
1241 
1242 
1244  ''' `X = X - a` where `a` is a real scalar and `X` is a real-valued
1245  field (DoF-wise subtraction of a scalar value from field elements).
1246 
1247  '''
1248  _case_name = "inc_X_minus_a"
1249  _datatype = "real"
1250 
1251  @classmethod
1252  def metadata(cls):
1253  '''Returns the kernel metadata describing this built-in.
1254 
1255  :returns: kernel metadata describing this built-in.
1256  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
1257 
1258  '''
1259  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
1260  return cls._builtin_metadata_builtin_metadata([
1261  FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1"),
1262  ScalarArgMetadata(gh_datatype, "gh_read")])
1263 
1265  '''
1266  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
1267  This BuiltIn node is replaced by an Assignment node.
1268 
1269  :returns: the lowered version of this node.
1270  :rtype: :py:class:`psyclone.psyir.node.Node`
1271 
1272  '''
1273  # Get indexed references for each of the field (proxy) arguments.
1274  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
1275  # Get a reference for the kernel scalar argument.
1276  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
1277 
1278  # Create the PSyIR for the kernel:
1279  # proxy0%data(df) = proxy0%data(df) - ascalar
1280  lhs = arg_refs[0]
1281  rhs = BinaryOperation.create(BinaryOperation.Operator.SUB,
1282  lhs.copy(), scalar_args[0])
1283 
1284  # Create assignment and replace node
1285  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
1286 
1287 
1289  ''' `Z = a*X - Y` where `a` is a real scalar and `Z`, `X` and
1290  `Y` are real-valued fields.
1291 
1292  '''
1293  _case_name = "aX_minus_Y"
1294  _datatype = "real"
1295 
1296  @classmethod
1297  def metadata(cls):
1298  '''Returns the kernel metadata describing this built-in.
1299 
1300  :returns: kernel metadata describing this built-in.
1301  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
1302 
1303  '''
1304  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
1305  return cls._builtin_metadata_builtin_metadata([
1306  FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"),
1307  ScalarArgMetadata(gh_datatype, "gh_read"),
1308  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1"),
1309  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
1310 
1312  '''
1313  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
1314  This BuiltIn node is replaced by an Assignment node.
1315 
1316  :returns: the lowered version of this node.
1317  :rtype: :py:class:`psyclone.psyir.node.Node`
1318 
1319  '''
1320  # Get indexed references for each of the field (proxy) arguments.
1321  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
1322  # Get a reference for the kernel scalar argument.
1323  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
1324 
1325  # Create the PSyIR for the kernel:
1326  # proxy0%data(df) = ascalar * proxy1%data(df) - proxy2%data(df)
1327  lhs = arg_refs[0]
1328  mult_op = BinaryOperation.create(BinaryOperation.Operator.MUL,
1329  scalar_args[0], arg_refs[1])
1330  rhs = BinaryOperation.create(BinaryOperation.Operator.SUB,
1331  mult_op, arg_refs[2])
1332 
1333  # Create assignment and replace node
1334  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
1335 
1336 
1338  ''' `Z = X - b*Y` where `b` is a real scalar and `Z`, `X` and
1339  `Y` are real-valued fields.
1340 
1341  '''
1342  _case_name = "X_minus_bY"
1343  _datatype = "real"
1344 
1345  @classmethod
1346  def metadata(cls):
1347  '''Returns the kernel metadata describing this built-in.
1348 
1349  :returns: kernel metadata describing this built-in.
1350  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
1351 
1352  '''
1353  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
1354  return cls._builtin_metadata_builtin_metadata([
1355  FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"),
1356  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1"),
1357  ScalarArgMetadata(gh_datatype, "gh_read"),
1358  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
1359 
1361  '''
1362  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
1363  This BuiltIn node is replaced by an Assignment node.
1364 
1365  :returns: the lowered version of this node.
1366  :rtype: :py:class:`psyclone.psyir.node.Node`
1367 
1368  '''
1369  # Get indexed references for each of the field (proxy) arguments.
1370  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
1371  # Get a reference for the kernel scalar argument.
1372  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
1373 
1374  # Create the PSyIR for the kernel:
1375  # proxy0%data(df) = proxy1%data(df) - bscalar * proxy2%data(df)
1376  lhs = arg_refs[0]
1377  mult_op = BinaryOperation.create(BinaryOperation.Operator.MUL,
1378  scalar_args[0], arg_refs[2])
1379  rhs = BinaryOperation.create(BinaryOperation.Operator.SUB,
1380  arg_refs[1], mult_op)
1381 
1382  # Create assignment and replace node
1383  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
1384 
1385 
1387  ''' `X = X - b*Y` where `b` is a real scalar and `X` and `Y` are
1388  real-valued fields.
1389 
1390  '''
1391  _case_name = "inc_X_minus_bY"
1392  _datatype = "real"
1393 
1394  @classmethod
1395  def metadata(cls):
1396  '''Returns the kernel metadata describing this built-in.
1397 
1398  :returns: kernel metadata describing this built-in.
1399  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
1400 
1401  '''
1402  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
1403  return cls._builtin_metadata_builtin_metadata([
1404  FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1"),
1405  ScalarArgMetadata(gh_datatype, "gh_read"),
1406  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
1407 
1409  '''
1410  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
1411  This BuiltIn node is replaced by an Assignment node.
1412 
1413  :returns: the lowered version of this node.
1414  :rtype: :py:class:`psyclone.psyir.node.Node`
1415 
1416  '''
1417  # Get indexed references for each of the field (proxy) arguments.
1418  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
1419  # Get a reference for the kernel scalar argument.
1420  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
1421 
1422  # Create the PSyIR for the kernel:
1423  # proxy0%data(df) = proxy0%data(df) - bscalar * proxy1%data(df)
1424  lhs = arg_refs[0]
1425  mult_op = BinaryOperation.create(BinaryOperation.Operator.MUL,
1426  scalar_args[0], arg_refs[1])
1427  rhs = BinaryOperation.create(BinaryOperation.Operator.SUB,
1428  lhs.copy(), mult_op)
1429 
1430  # Create assignment and replace node
1431  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
1432 
1433 
1435  ''' `Z = a*X - b*Y` where `a` and `b` are real scalars and `Z`, `X` and
1436  `Y` are real-valued fields.
1437 
1438  '''
1439  _case_name = "aX_minus_bY"
1440  _datatype = "real"
1441 
1442  @classmethod
1443  def metadata(cls):
1444  '''Returns the kernel metadata describing this built-in.
1445 
1446  :returns: kernel metadata describing this built-in.
1447  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
1448 
1449  '''
1450  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
1451  return cls._builtin_metadata_builtin_metadata([
1452  FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"),
1453  ScalarArgMetadata(gh_datatype, "gh_read"),
1454  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1"),
1455  ScalarArgMetadata(gh_datatype, "gh_read"),
1456  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
1457 
1459  '''
1460  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
1461  This BuiltIn node is replaced by an Assignment node.
1462 
1463  :returns: the lowered version of this node.
1464  :rtype: :py:class:`psyclone.psyir.node.Node`
1465 
1466  '''
1467  # Get indexed references for each of the field (proxy) arguments.
1468  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
1469  # Get a reference for the kernel scalar argument.
1470  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
1471 
1472  # Create the PSyIR for the kernel:
1473  # proxy0%data(df) = ascalar * proxy1%data(df) -
1474  # bscalar * proxy2%data(df)
1475  lhs = arg_refs[0]
1476  mult_op_a = BinaryOperation.create(BinaryOperation.Operator.MUL,
1477  scalar_args[0], arg_refs[1])
1478  mult_op_b = BinaryOperation.create(BinaryOperation.Operator.MUL,
1479  scalar_args[1], arg_refs[2])
1480  rhs = BinaryOperation.create(BinaryOperation.Operator.SUB,
1481  mult_op_a, mult_op_b)
1482 
1483  # Create assignment and replace node
1484  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
1485 
1486 
1487 # ------------------------------------------------------------------- #
1488 # ============== Multiplying (scaled) real fields =================== #
1489 # ------------------------------------------------------------------- #
1490 
1491 
1493  ''' DoF-wise product of one, real-valued, field with another with
1494  the result returned as a third, real-valued, field.
1495 
1496  '''
1497  _case_name = "X_times_Y"
1498  _datatype = "real"
1499 
1500  @classmethod
1501  def metadata(cls):
1502  '''Returns the kernel metadata describing this built-in.
1503 
1504  :returns: kernel metadata describing this built-in.
1505  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
1506 
1507  '''
1508  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
1509  return cls._builtin_metadata_builtin_metadata([
1510  FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"),
1511  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1"),
1512  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
1513 
1514  def __str__(self):
1515  return (f"Built-in: {self._case_name} (multiply "
1516  f"{self._datatype}-valued fields)")
1517 
1519  '''
1520  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
1521  This BuiltIn node is replaced by an Assignment node.
1522 
1523  :returns: the lowered version of this node.
1524  :rtype: :py:class:`psyclone.psyir.node.Node`
1525 
1526  '''
1527  # Get indexed references for each of the field (proxy) arguments.
1528  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
1529 
1530  # Create the PSyIR for the kernel:
1531  # proxy0%data(df) = proxy1%data(df) * proxy2%data(df)
1532  lhs = arg_refs[0]
1533  rhs = BinaryOperation.create(BinaryOperation.Operator.MUL,
1534  arg_refs[1], arg_refs[2])
1535 
1536  # Create assignment and replace node
1537  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
1538 
1539 
1541  ''' Multiply the first, real-valued, field by the second and return it.
1542 
1543  '''
1544  _case_name = "inc_X_times_Y"
1545  _datatype = "real"
1546 
1547  @classmethod
1548  def metadata(cls):
1549  '''Returns the kernel metadata describing this built-in.
1550 
1551  :returns: kernel metadata describing this built-in.
1552  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
1553 
1554  '''
1555  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
1556  return cls._builtin_metadata_builtin_metadata([
1557  FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1"),
1558  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
1559 
1560  def __str__(self):
1561  return (f"Built-in: {self._case_name} (multiply one "
1562  f"{self._datatype}-valued field by another)")
1563 
1565  '''
1566  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
1567  This BuiltIn node is replaced by an Assignment node.
1568 
1569  :returns: the lowered version of this node.
1570  :rtype: :py:class:`psyclone.psyir.node.Node`
1571 
1572  '''
1573  # Get indexed refs for both of the field (proxy) arguments.
1574  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
1575 
1576  # Create the PSyIR for the kernel:
1577  # proxy0%data(df) = proxy0%data(df) * proxy1%data(df)
1578  lhs = arg_refs[0]
1579  rhs = BinaryOperation.create(BinaryOperation.Operator.MUL,
1580  lhs.copy(), arg_refs[1])
1581 
1582  # Create assignment and replace node
1583  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
1584 
1585 
1587  ''' `X = a*X*Y` where `a` is a real scalar and `X` and `Y` are
1588  real-valued fields.
1589 
1590  '''
1591  _case_name = "inc_aX_times_Y"
1592  _datatype = "real"
1593 
1594  @classmethod
1595  def metadata(cls):
1596  '''Returns the kernel metadata describing this built-in.
1597 
1598  :returns: kernel metadata describing this built-in.
1599  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
1600 
1601  '''
1602  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
1603  return cls._builtin_metadata_builtin_metadata([
1604  ScalarArgMetadata(gh_datatype, "gh_read"),
1605  FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1"),
1606  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
1607 
1609  '''
1610  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
1611  This BuiltIn node is replaced by an Assignment node.
1612 
1613  :returns: the lowered version of this node.
1614  :rtype: :py:class:`psyclone.psyir.node.Node`
1615 
1616  '''
1617  # Get indexed references for each of the field (proxy) arguments.
1618  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
1619  # Get a reference for the kernel scalar argument.
1620  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
1621 
1622  # Create the PSyIR for the kernel:
1623  # proxy0%data(df) = ascalar * proxy0%data(df) * proxy1%data(df)
1624  lhs = arg_refs[0]
1625  mult_op = BinaryOperation.create(BinaryOperation.Operator.MUL,
1626  scalar_args[0], lhs.copy())
1627  rhs = BinaryOperation.create(BinaryOperation.Operator.MUL,
1628  mult_op, arg_refs[1])
1629 
1630  # Create assignment and replace node
1631  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
1632 
1633 
1634 # ------------------------------------------------------------------- #
1635 # ============== Scaling real fields ================================ #
1636 # ------------------------------------------------------------------- #
1637 
1638 
1640  ''' Multiply the first, real-valued, field by a real scalar and
1641  return the result as a second, real-valued, field (`Y = a*X`).
1642 
1643  '''
1644  _case_name = "a_times_X"
1645  _datatype = "real"
1646 
1647  @classmethod
1648  def metadata(cls):
1649  '''Returns the kernel metadata describing this built-in.
1650 
1651  :returns: kernel metadata describing this built-in.
1652  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
1653 
1654  '''
1655  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
1656  return cls._builtin_metadata_builtin_metadata([
1657  FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"),
1658  ScalarArgMetadata(gh_datatype, "gh_read"),
1659  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
1660 
1661  def __str__(self):
1662  return (f"Built-in: {self._case_name} (copy a scaled "
1663  f"{self._datatype}-valued field)")
1664 
1666  '''
1667  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
1668  This BuiltIn node is replaced by an Assignment node.
1669 
1670  :returns: the lowered version of this node.
1671  :rtype: :py:class:`psyclone.psyir.node.Node`
1672 
1673  '''
1674  # Get indexed references for each of the field (proxy) arguments.
1675  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
1676  # Get a reference for the kernel scalar argument.
1677  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
1678 
1679  # Create the PSyIR for the kernel:
1680  # proxy0%data(df) = ascalar * proxy1%data(df)
1681  lhs = arg_refs[0]
1682  rhs = BinaryOperation.create(BinaryOperation.Operator.MUL,
1683  scalar_args[0], arg_refs[1])
1684 
1685  # Create assignment and replace node
1686  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
1687 
1688 
1690  ''' Multiply a real-valued field by a real scalar and return it.
1691 
1692  '''
1693  _case_name = "inc_a_times_X"
1694  _datatype = "real"
1695 
1696  @classmethod
1697  def metadata(cls):
1698  '''Returns the kernel metadata describing this built-in.
1699 
1700  :returns: kernel metadata describing this built-in.
1701  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
1702 
1703  '''
1704  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
1705  return cls._builtin_metadata_builtin_metadata([
1706  ScalarArgMetadata(gh_datatype, "gh_read"),
1707  FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1")])
1708 
1709  def __str__(self):
1710  return (f"Built-in: {self._case_name} (scale "
1711  f"{a_or_an(self._datatype)} {self._datatype}-valued field)")
1712 
1714  '''
1715  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
1716  This BuiltIn node is replaced by an Assignment node.
1717 
1718  :returns: the lowered version of this node.
1719  :rtype: :py:class:`psyclone.psyir.node.Node`
1720 
1721  '''
1722  # Get indexed references for each of the field (proxy) arguments.
1723  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
1724  # Get a reference for the kernel scalar argument.
1725  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
1726 
1727  # Create the PSyIR for the kernel:
1728  # proxy0%data(df) = ascalar * proxy0%data(df)
1729  lhs = arg_refs[0]
1730  rhs = BinaryOperation.create(BinaryOperation.Operator.MUL,
1731  scalar_args[0], lhs.copy())
1732 
1733  # Create assignment and replace node
1734  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
1735 
1736 # ------------------------------------------------------------------- #
1737 # ============== Dividing real fields =============================== #
1738 # ------------------------------------------------------------------- #
1739 
1740 
1742  ''' Divide the first, real-valued, field by the second and return
1743  the result as a third, real-valued, field.
1744 
1745  '''
1746  _case_name = "X_divideby_Y"
1747  _datatype = "real"
1748 
1749  @classmethod
1750  def metadata(cls):
1751  '''Returns the kernel metadata describing this built-in.
1752 
1753  :returns: kernel metadata describing this built-in.
1754  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
1755 
1756  '''
1757  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
1758  return cls._builtin_metadata_builtin_metadata([
1759  FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"),
1760  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1"),
1761  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
1762 
1763  def __str__(self):
1764  return (f"Built-in: {self._case_name} (divide "
1765  f"{self._datatype}-valued fields)")
1766 
1768  '''
1769  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
1770  This BuiltIn node is replaced by an Assignment node.
1771 
1772  :returns: the lowered version of this node.
1773  :rtype: :py:class:`psyclone.psyir.node.Node`
1774 
1775  '''
1776  # Get indexed references for each of the field (proxy) arguments.
1777  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
1778 
1779  # Create the PSyIR for the kernel:
1780  # proxy0%data(df) = proxy1%data(df) / proxy2%data(df)
1781  lhs = arg_refs[0]
1782  rhs = BinaryOperation.create(BinaryOperation.Operator.DIV,
1783  arg_refs[1], arg_refs[2])
1784 
1785  # Create assignment and replace node
1786  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
1787 
1788 
1790  ''' Divide the first, real-valued, field by the second and return it.
1791 
1792  '''
1793  _case_name = "inc_X_divideby_Y"
1794  _datatype = "real"
1795 
1796  @classmethod
1797  def metadata(cls):
1798  '''Returns the kernel metadata describing this built-in.
1799 
1800  :returns: kernel metadata describing this built-in.
1801  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
1802 
1803  '''
1804  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
1805  return cls._builtin_metadata_builtin_metadata([
1806  FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1"),
1807  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
1808 
1809  def __str__(self):
1810  return (f"Built-in: {self._case_name} (divide one "
1811  f"{self._datatype}-valued field by another)")
1812 
1814  '''
1815  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
1816  This BuiltIn node is replaced by an Assignment node.
1817 
1818  :returns: the lowered version of this node.
1819  :rtype: :py:class:`psyclone.psyir.node.Node`
1820 
1821  '''
1822  # Get indexed refs for both of the field (proxy) arguments.
1823  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
1824 
1825  # Create the PSyIR for the kernel:
1826  # proxy0%data(df) = proxy0%data(df) / proxy1%data(df)
1827  lhs = arg_refs[0]
1828  rhs = BinaryOperation.create(BinaryOperation.Operator.DIV,
1829  lhs.copy(), arg_refs[1])
1830 
1831  # Create assignment and replace node
1832  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
1833 
1834 
1836  ''' Divide a real-valued field by a real scalar and return the
1837  result in another, real-valued, field.
1838 
1839  '''
1840  _case_name = "X_divideby_a"
1841  _datatype = "real"
1842 
1843  @classmethod
1844  def metadata(cls):
1845  '''Returns the kernel metadata describing this built-in.
1846 
1847  :returns: kernel metadata describing this built-in.
1848  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
1849 
1850  '''
1851  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
1852  return cls._builtin_metadata_builtin_metadata([
1853  FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"),
1854  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1"),
1855  ScalarArgMetadata(gh_datatype, "gh_read")])
1856 
1857  def __str__(self):
1858  return (f"Built-in: {self._case_name} (divide a real-valued field "
1859  f"by {a_or_an(self._datatype)} {self._datatype} scalar "
1860  "(Y = X/a))")
1861 
1863  '''
1864  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
1865  This BuiltIn node is replaced by an Assignment node.
1866 
1867  :returns: the lowered version of this node.
1868  :rtype: :py:class:`psyclone.psyir.node.Node`
1869 
1870  '''
1871  # Get indexed references for each of the field (proxy) arguments.
1872  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
1873  # Get a reference for the kernel scalar argument.
1874  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
1875 
1876  # Create the PSyIR for the kernel:
1877  # proxy0%data(df) = proxy1%data(df) / ascalar
1878  lhs = arg_refs[0]
1879  rhs = BinaryOperation.create(BinaryOperation.Operator.DIV,
1880  arg_refs[1], scalar_args[0])
1881 
1882  # Create assignment and replace node
1883  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
1884 
1885 
1887  ''' Divide a real-valued field by a real scalar and return it.
1888 
1889  '''
1890  _case_name = "inc_X_divideby_a"
1891  _datatype = "real"
1892 
1893  @classmethod
1894  def metadata(cls):
1895  '''Returns the kernel metadata describing this built-in.
1896 
1897  :returns: kernel metadata describing this built-in.
1898  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
1899 
1900  '''
1901  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
1902  return cls._builtin_metadata_builtin_metadata([
1903  FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1"),
1904  ScalarArgMetadata(gh_datatype, "gh_read")])
1905 
1906  def __str__(self):
1907  return (f"Built-in: {self._case_name} (divide a real-valued field "
1908  f"by {a_or_an(self._datatype)} {self._datatype} scalar "
1909  f"(X = X/a))")
1910 
1912  '''
1913  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
1914  This BuiltIn node is replaced by an Assignment node.
1915 
1916  :returns: the lowered version of this node.
1917  :rtype: :py:class:`psyclone.psyir.node.Node`
1918 
1919  '''
1920  # Get indexed references for each of the field (proxy) arguments.
1921  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
1922  # Get a reference for the kernel scalar argument.
1923  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
1924 
1925  # Create the PSyIR for the kernel:
1926  # proxy0%data(df) = proxy0%data(df) / ascalar
1927  lhs = arg_refs[0]
1928  rhs = BinaryOperation.create(BinaryOperation.Operator.DIV,
1929  lhs.copy(), scalar_args[0])
1930 
1931  # Create assignment and replace node
1932  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
1933 
1934 # ------------------------------------------------------------------- #
1935 # ============== Inverse scaling of real fields ===================== #
1936 # ------------------------------------------------------------------- #
1937 
1938 
1940  ''' DoF-wise division of a scalar value `a` by the elements
1941  of a real-valued field, `X`, storing the result in another,
1942  real-valued, field, `Y` (`Y = a/X`).
1943 
1944  '''
1945  _case_name = "a_divideby_X"
1946  _datatype = "real"
1947 
1948  @classmethod
1949  def metadata(cls):
1950  '''Returns the kernel metadata describing this built-in.
1951 
1952  :returns: kernel metadata describing this built-in.
1953  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
1954 
1955  '''
1956  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
1957  return cls._builtin_metadata_builtin_metadata([
1958  FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"),
1959  ScalarArgMetadata(gh_datatype, "gh_read"),
1960  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
1961 
1962  def __str__(self):
1963  return (f"Built-in: {self._case_name} (inverse scaling of "
1964  f"{a_or_an(self._datatype)} {self._datatype}-valued "
1965  f"field (Y = a/X))")
1966 
1968  '''
1969  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
1970  This BuiltIn node is replaced by an Assignment node.
1971 
1972  :returns: the lowered version of this node.
1973  :rtype: :py:class:`psyclone.psyir.node.Node`
1974 
1975  '''
1976  # Get indexed references for each of the field (proxy) arguments.
1977  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
1978  # Get a reference for the kernel scalar argument.
1979  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
1980 
1981  # Create the PSyIR for the kernel:
1982  # proxy0%data(df) = ascalar / proxy1%data(df)
1983  lhs = arg_refs[0]
1984  rhs = BinaryOperation.create(BinaryOperation.Operator.DIV,
1985  scalar_args[0], arg_refs[1])
1986 
1987  # Create assignment and replace node
1988  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
1989 
1990 
1992  ''' DoF-wise division of a scalar value `a` by the elements
1993  of a real-valued field, `X`, storing the result in the same
1994  field (`X = a/X`).
1995 
1996  '''
1997  _case_name = "inc_a_divideby_X"
1998  _datatype = "real"
1999 
2000  @classmethod
2001  def metadata(cls):
2002  '''Returns the kernel metadata describing this built-in.
2003 
2004  :returns: kernel metadata describing this built-in.
2005  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
2006 
2007  '''
2008  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
2009  return cls._builtin_metadata_builtin_metadata([
2010  ScalarArgMetadata(gh_datatype, "gh_read"),
2011  FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1")])
2012 
2013  def __str__(self):
2014  return (f"Built-in: {self._case_name} (inverse scaling of "
2015  f"{a_or_an(self._datatype)} {self._datatype}-valued "
2016  f"field (X = a/X))")
2017 
2019  '''
2020  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
2021  This BuiltIn node is replaced by an Assignment node.
2022 
2023  :returns: the lowered version of this node.
2024  :rtype: :py:class:`psyclone.psyir.node.Node`
2025 
2026  '''
2027  # Get indexed references for each of the field (proxy) arguments.
2028  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
2029  # Get a reference for the kernel scalar argument.
2030  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
2031 
2032  # Create the PSyIR for the kernel:
2033  # proxy0%data(df) = ascalar / proxy0%data(df)
2034  lhs = arg_refs[0]
2035  rhs = BinaryOperation.create(BinaryOperation.Operator.DIV,
2036  scalar_args[0], lhs.copy())
2037 
2038  # Create assignment and replace node
2039  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
2040 
2041 
2042 # ------------------------------------------------------------------- #
2043 # ============== Raising a real field to a scalar =================== #
2044 # ------------------------------------------------------------------- #
2045 
2046 
2048  ''' Raise a real-valued field to a real power and return it.
2049 
2050  '''
2051  _case_name = "inc_X_powreal_a"
2052  _datatype = "real"
2053 
2054  @classmethod
2055  def metadata(cls):
2056  '''Returns the kernel metadata describing this built-in.
2057 
2058  :returns: kernel metadata describing this built-in.
2059  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
2060 
2061  '''
2062  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
2063  return cls._builtin_metadata_builtin_metadata([
2064  FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1"),
2065  ScalarArgMetadata("gh_real", "gh_read")])
2066 
2067  def __str__(self):
2068  return (f"Built-in: {self._case_name} (raise "
2069  f"{a_or_an(self._datatype)} {self._datatype}-valued field "
2070  f"to a real power)")
2071 
2073  '''
2074  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
2075  This BuiltIn node is replaced by an Assignment node.
2076 
2077  :returns: the lowered version of this node.
2078  :rtype: :py:class:`psyclone.psyir.node.Node`
2079 
2080  '''
2081  # Get PSyIR for each of the arguments.
2082  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
2083  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
2084 
2085  # Create the PSyIR for the kernel:
2086  # proxy0%data(df) = proxy0%data(df) ** real_power
2087  lhs = arg_refs[0]
2088  rhs = BinaryOperation.create(BinaryOperation.Operator.POW,
2089  lhs.copy(), scalar_args[0])
2090 
2091  # Create assignment and replace node
2092  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
2093 
2094 
2096  ''' Raise a real-valued field to an integer power and return it.
2097 
2098  '''
2099  _case_name = "inc_X_powint_n"
2100  _datatype = "real"
2101 
2102  @classmethod
2103  def metadata(cls):
2104  '''Returns the kernel metadata describing this built-in.
2105 
2106  :returns: kernel metadata describing this built-in.
2107  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
2108 
2109  '''
2110  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
2111  return cls._builtin_metadata_builtin_metadata([
2112  FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1"),
2113  ScalarArgMetadata("gh_integer", "gh_read")])
2114 
2115  def __str__(self):
2116  return (f"Built-in: {self._case_name} (raise "
2117  f"{a_or_an(self._datatype)} {self._datatype}-valued field "
2118  f"to an integer power)")
2119 
2121  '''
2122  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
2123  This BuiltIn node is replaced by an Assignment node.
2124 
2125  :returns: the lowered version of this node.
2126  :rtype: :py:class:`psyclone.psyir.node.Node`
2127 
2128  '''
2129  # Get PSyIR for each of the arguments.
2130  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
2131  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
2132 
2133  # Create the PSyIR for the kernel:
2134  # proxy0%data(df) = proxy0%data(df) ** int_power
2135  lhs = arg_refs[0]
2136  rhs = BinaryOperation.create(BinaryOperation.Operator.POW,
2137  lhs.copy(), scalar_args[0])
2138 
2139  # Create assignment and replace node
2140  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
2141 
2142 
2143 # ------------------------------------------------------------------- #
2144 # ============== Setting real field elements to a value ============ #
2145 # ------------------------------------------------------------------- #
2146 
2147 
2149  ''' Set a real-valued field equal to a real scalar value.
2150 
2151  '''
2152  _case_name = "setval_c"
2153  _datatype = "real"
2154 
2155  @classmethod
2156  def metadata(cls):
2157  '''Returns the kernel metadata describing this built-in.
2158 
2159  :returns: kernel metadata describing this built-in.
2160  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
2161 
2162  '''
2163  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
2164  return cls._builtin_metadata_builtin_metadata([
2165  FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"),
2166  ScalarArgMetadata(gh_datatype, "gh_read")])
2167 
2168  def __str__(self):
2169  return (f"Built-in: {self._case_name} (set {a_or_an(self._datatype)} "
2170  f"{self._datatype}-valued field to a {self._datatype} "
2171  f"scalar value)")
2172 
2174  '''
2175  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
2176  This BuiltIn node is replaced by an Assignment node.
2177 
2178  :returns: the lowered version of this node.
2179  :rtype: :py:class:`psyclone.psyir.node.Node`
2180 
2181  '''
2182  # Get indexed references for each of the field (proxy) arguments.
2183  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
2184  # Get a reference for the kernel scalar argument.
2185  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
2186 
2187  # Create the PSyIR for the kernel:
2188  # proxy0%data(df) = ascalar
2189  lhs = arg_refs[0]
2190  rhs = scalar_args[0]
2191 
2192  # Create assignment and replace node
2193  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
2194 
2195 
2197  ''' Set a real-valued field equal to another, real-valued, field.
2198 
2199  '''
2200  _case_name = "setval_X"
2201  _datatype = "real"
2202 
2203  @classmethod
2204  def metadata(cls):
2205  '''Returns the kernel metadata describing this built-in.
2206 
2207  :returns: kernel metadata describing this built-in.
2208  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
2209 
2210  '''
2211  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
2212  return cls._builtin_metadata_builtin_metadata([
2213  FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"),
2214  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
2215 
2216  def __str__(self):
2217  return (f"Built-in: {self._case_name} (set {a_or_an(self._datatype)} "
2218  f"{self._datatype}-valued field equal to another such field)")
2219 
2221  '''
2222  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
2223  This BuiltIn node is replaced by an Assignment node.
2224 
2225  :returns: the lowered version of this node.
2226  :rtype: :py:class:`psyclone.psyir.node.Node`
2227 
2228  '''
2229  # Get indexed refs for both of the field (proxy) arguments.
2230  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
2231 
2232  # Create the PSyIR for the kernel:
2233  # proxy0%data(df) = proxy1%data(df)
2234  lhs = arg_refs[0]
2235  rhs = arg_refs[1]
2236 
2237  # Create assignment and replace node
2238  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
2239 
2240 
2242  ''' Fill a real-valued field with pseudo-random numbers.
2243 
2244  '''
2245  _case_name = "setval_random"
2246  _datatype = "real"
2247 
2248  @classmethod
2249  def metadata(cls):
2250  '''Returns the kernel metadata describing this built-in.
2251 
2252  :returns: kernel metadata describing this built-in.
2253  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
2254 
2255  '''
2256  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
2257  return cls._builtin_metadata_builtin_metadata([
2258  FieldArgMetadata(gh_datatype, "gh_write", "any_space_1")])
2259 
2260  def __str__(self):
2261  return (f"Built-in: {self._case_name} (fill {a_or_an(self._datatype)} "
2262  f"{self._datatype}-valued field with pseudo-random numbers)")
2263 
2265  '''
2266  Lowers this LFRic built-in kernel to language-level PSyIR.
2267  This BuiltIn node is replaced by an IntrinsicCall node.
2268 
2269  :returns: the lowered version of this node.
2270  :rtype: :py:class:`psyclone.psyir.node.IntrinsicCall`
2271 
2272  '''
2273  # Get indexed refs for the field (proxy) argument.
2274  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
2275 
2276  # Create the PSyIR for the kernel:
2277  # call random_number(proxy0%data(df))
2278  call = IntrinsicCall.create(IntrinsicCall.Intrinsic.RANDOM_NUMBER,
2279  arg_refs)
2280  # Add a preceding comment to the Assignment
2281  call.preceding_comment = str(self)
2282  # Finally, replace this kernel node with the Assignment
2283  self.replace_with(call)
2284  return call
2285 
2286 # ------------------------------------------------------------------- #
2287 # ============== Inner product of real fields ======================= #
2288 # ------------------------------------------------------------------- #
2289 
2290 
2292  ''' Calculates the inner product of two real-valued fields,
2293  `innprod = SUM( X(:)*Y(:) )`.
2294 
2295  '''
2296  _case_name = "X_innerproduct_Y"
2297  _datatype = "real"
2298 
2299  @classmethod
2300  def metadata(cls):
2301  '''Returns the kernel metadata describing this built-in.
2302 
2303  :returns: kernel metadata describing this built-in.
2304  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
2305 
2306  '''
2307  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
2308  return cls._builtin_metadata_builtin_metadata([
2309  ScalarArgMetadata(gh_datatype, "gh_sum"),
2310  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1"),
2311  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
2312 
2314  '''
2315  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
2316  This BuiltIn node is replaced by an Assignment node.
2317 
2318  :returns: the lowered version of this node.
2319  :rtype: :py:class:`psyclone.psyir.node.Node`
2320 
2321  '''
2322  # Get indexed references for the field (proxy) argument.
2323  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
2324  # Get a reference for the kernel scalar reduction argument.
2325  lhs = self._reduction_reference_reduction_reference()
2326  # Create the PSyIR for the kernel:
2327  # asum = asum + proxy0%data(df) * proxy1%data(df)
2328  mult_op = BinaryOperation.create(BinaryOperation.Operator.MUL,
2329  arg_refs[0], arg_refs[1])
2330  rhs = BinaryOperation.create(BinaryOperation.Operator.ADD,
2331  lhs.copy(), mult_op)
2332 
2333  # Create assignment and replace node
2334  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
2335 
2336 
2338  ''' Calculates the inner product of one real-valued field by itself,
2339  `innprod = SUM( X(:)*X(:) )`.
2340 
2341  '''
2342  _case_name = "X_innerproduct_X"
2343  _datatype = "real"
2344 
2345  @classmethod
2346  def metadata(cls):
2347  '''Returns the kernel metadata describing this built-in.
2348 
2349  :returns: kernel metadata describing this built-in.
2350  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
2351 
2352  '''
2353  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
2354  return cls._builtin_metadata_builtin_metadata([
2355  ScalarArgMetadata(gh_datatype, "gh_sum"),
2356  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
2357 
2359  '''
2360  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
2361  This BuiltIn node is replaced by an Assignment node.
2362 
2363  :returns: the lowered version of this node.
2364  :rtype: :py:class:`psyclone.psyir.node.Node`
2365 
2366  '''
2367  # Get indexed references for the field (proxy) argument.
2368  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
2369  # Get a reference for the kernel scalar reduction argument.
2370  lhs = self._reduction_reference_reduction_reference()
2371  # Create the PSyIR for the kernel:
2372  # asum = asum + proxy0%data(df) * proxy0%data(df)
2373  mult_op = BinaryOperation.create(BinaryOperation.Operator.MUL,
2374  arg_refs[0].copy(), arg_refs[0])
2375  rhs = BinaryOperation.create(BinaryOperation.Operator.ADD,
2376  lhs.copy(), mult_op)
2377 
2378  # Create assignment and replace node
2379  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
2380 
2381 
2382 # ------------------------------------------------------------------- #
2383 # ============== Sum of real field elements ========================= #
2384 # ------------------------------------------------------------------- #
2385 
2386 
2388  ''' Computes the sum of the elements of a real-valued field.
2389 
2390  '''
2391  _case_name = "sum_X"
2392  _datatype = "real"
2393 
2394  @classmethod
2395  def metadata(cls):
2396  '''Returns the kernel metadata describing this built-in.
2397 
2398  :returns: kernel metadata describing this built-in.
2399  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
2400 
2401  '''
2402  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
2403  return cls._builtin_metadata_builtin_metadata([
2404  ScalarArgMetadata(gh_datatype, "gh_sum"),
2405  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
2406 
2407  def __str__(self):
2408  return (f"Built-in: {self._case_name} (sum {a_or_an(self._datatype)} "
2409  f"{self._datatype}-valued field)")
2410 
2412  '''
2413  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
2414  This BuiltIn node is replaced by an Assignment node.
2415 
2416  :returns: the lowered version of this node.
2417  :rtype: :py:class:`psyclone.psyir.node.Node`
2418 
2419  '''
2420  # Get indexed references for the field (proxy) argument.
2421  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
2422  # Get a reference for the kernel scalar reduction argument.
2423  lhs = self._reduction_reference_reduction_reference()
2424  # Create the PSyIR for the kernel:
2425  # asum = asum + proxy0%data(df)
2426  rhs = BinaryOperation.create(BinaryOperation.Operator.ADD,
2427  lhs.copy(), arg_refs[0])
2428 
2429  # Create assignment and replace node
2430  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
2431 
2432 
2433 # ------------------------------------------------------------------- #
2434 # ============== Sign of real field elements ======================== #
2435 # ------------------------------------------------------------------- #
2436 
2437 
2439  ''' Returns the sign of a real-valued field elements using the
2440  Fortran intrinsic `sign` function, `Y = sign(a, X)`.
2441 
2442  '''
2443  _case_name = "sign_X"
2444  _datatype = "real"
2445 
2446  @classmethod
2447  def metadata(cls):
2448  '''Returns the kernel metadata describing this built-in.
2449 
2450  :returns: kernel metadata describing this built-in.
2451  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
2452 
2453  '''
2454  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
2455  return cls._builtin_metadata_builtin_metadata([
2456  FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"),
2457  ScalarArgMetadata(gh_datatype, "gh_read"),
2458  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
2459 
2460  def __str__(self):
2461  return (f"Built-in: {self._case_name} (sign of "
2462  f"{a_or_an(self._datatype)} {self._datatype}-valued field)")
2463 
2465  '''
2466  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
2467  This BuiltIn node is replaced by an Assignment node.
2468 
2469  :returns: the lowered version of this node.
2470  :rtype: :py:class:`psyclone.psyir.node.Node`
2471 
2472  '''
2473  # Get indexed references for each of the field (proxy) arguments.
2474  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
2475  # Get a reference for the kernel scalar argument.
2476  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
2477 
2478  # Create the PSyIR for the kernel:
2479  # proxy0%data(df) = SIGN(ascalar, proxy1%data)
2480  lhs = arg_refs[0]
2481  rhs = IntrinsicCall.create(IntrinsicCall.Intrinsic.SIGN,
2482  [scalar_args[0], arg_refs[1]])
2483 
2484  # Create assignment and replace node
2485  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
2486 
2487 
2488 # ------------------------------------------------------------------- #
2489 # ============== Maximum of (real scalar, real field elements) ====== #
2490 # ------------------------------------------------------------------- #
2491 
2492 
2494  ''' Returns the maximum of a real scalar and real-valued field
2495  elements. The result is stored as another, real-valued, field:
2496  `Y = max(a, X)`.
2497 
2498  '''
2499  _case_name = "max_aX"
2500  _datatype = "real"
2501 
2502  @classmethod
2503  def metadata(cls):
2504  '''Returns the kernel metadata describing this built-in.
2505 
2506  :returns: kernel metadata describing this built-in.
2507  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
2508 
2509  '''
2510  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
2511  return cls._builtin_metadata_builtin_metadata([
2512  FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"),
2513  ScalarArgMetadata(gh_datatype, "gh_read"),
2514  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
2515 
2517  '''
2518  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
2519  This BuiltIn node is replaced by an Assignment node.
2520 
2521  :returns: the lowered version of this node.
2522  :rtype: :py:class:`psyclone.psyir.node.Node`
2523 
2524  '''
2525  # Get indexed references for each of the field (proxy) arguments.
2526  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
2527  # Get a reference for the kernel scalar argument.
2528  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
2529 
2530  # Create the PSyIR for the kernel:
2531  # proxy0%data(df) = MAX(ascalar, proxy1%data)
2532  lhs = arg_refs[0]
2533  rhs = IntrinsicCall.create(IntrinsicCall.Intrinsic.MAX,
2534  [scalar_args[0], arg_refs[1]])
2535 
2536  # Create assignment and replace node
2537  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
2538 
2539 
2541  ''' Returns the maximum of a real scalar and real-valued field
2542  elements. The result is stored in the same, real-valued, field:
2543  `X = max(a, X)`.
2544 
2545  '''
2546  _case_name = "inc_max_aX"
2547  _datatype = "real"
2548 
2549  @classmethod
2550  def metadata(cls):
2551  '''Returns the kernel metadata describing this built-in.
2552 
2553  :returns: kernel metadata describing this built-in.
2554  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
2555 
2556  '''
2557  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
2558  return cls._builtin_metadata_builtin_metadata([
2559  ScalarArgMetadata(gh_datatype, "gh_read"),
2560  FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1")])
2561 
2563  '''
2564  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
2565  This BuiltIn node is replaced by an Assignment node.
2566 
2567  :returns: the lowered version of this node.
2568  :rtype: :py:class:`psyclone.psyir.node.Node`
2569 
2570  '''
2571  # Get indexed references for each of the field (proxy) arguments.
2572  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
2573  # Get a reference for the kernel scalar argument.
2574  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
2575 
2576  # Create the PSyIR for the kernel:
2577  # proxy0%data(df) = MAX(ascalar, proxy0%data)
2578  lhs = arg_refs[0]
2579  rhs = IntrinsicCall.create(IntrinsicCall.Intrinsic.MAX,
2580  [scalar_args[0], lhs.copy()])
2581 
2582  # Create assignment and replace node
2583  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
2584 
2585 # ------------------------------------------------------------------- #
2586 # ============== Minimum of (real scalar, real field elements) ====== #
2587 # ------------------------------------------------------------------- #
2588 
2589 
2591  ''' Returns the minimum of a real scalar and real-valued field
2592  elements. The result is stored as another, real-valued, field:
2593  `Y = min(a, X)`.
2594 
2595  '''
2596  _case_name = "min_aX"
2597  _datatype = "real"
2598 
2599  @classmethod
2600  def metadata(cls):
2601  '''Returns the kernel metadata describing this built-in.
2602 
2603  :returns: kernel metadata describing this built-in.
2604  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
2605 
2606  '''
2607  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
2608  return cls._builtin_metadata_builtin_metadata([
2609  FieldArgMetadata(gh_datatype, "gh_write", "any_space_1"),
2610  ScalarArgMetadata(gh_datatype, "gh_read"),
2611  FieldArgMetadata(gh_datatype, "gh_read", "any_space_1")])
2612 
2614  '''
2615  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
2616  This BuiltIn node is replaced by an Assignment node.
2617 
2618  :returns: the lowered version of this node.
2619  :rtype: :py:class:`psyclone.psyir.node.Node`
2620 
2621  '''
2622  # Get indexed references for each of the field (proxy) arguments.
2623  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
2624  # Get a reference for the kernel scalar argument.
2625  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
2626 
2627  # Create the PSyIR for the kernel:
2628  # proxy0%data(df) = MIN(ascalar, proxy1%data)
2629  lhs = arg_refs[0]
2630  rhs = IntrinsicCall.create(IntrinsicCall.Intrinsic.MIN,
2631  [scalar_args[0], arg_refs[1]])
2632 
2633  # Create assignment and replace node
2634  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
2635 
2636 
2638  ''' Returns the minimum of a real scalar and real-valued field
2639  elements. The result is stored in the same, real-valued, field:
2640  `X = min(a, X)`.
2641 
2642  '''
2643  _case_name = "inc_min_aX"
2644  _datatype = "real"
2645 
2646  @classmethod
2647  def metadata(cls):
2648  '''Returns the kernel metadata describing this built-in.
2649 
2650  :returns: kernel metadata describing this built-in.
2651  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
2652 
2653  '''
2654  gh_datatype = LFRicConstants().MAPPING_INTRINSIC_TYPES[cls._datatype_datatype_datatype]
2655  return cls._builtin_metadata_builtin_metadata([
2656  ScalarArgMetadata(gh_datatype, "gh_read"),
2657  FieldArgMetadata(gh_datatype, "gh_readwrite", "any_space_1")])
2658 
2660  '''
2661  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
2662  This BuiltIn node is replaced by an Assignment node.
2663 
2664  :returns: the lowered version of this node.
2665  :rtype: :py:class:`psyclone.psyir.node.Node`
2666 
2667  '''
2668  # Get indexed references for each of the field (proxy) arguments.
2669  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
2670  # Get a reference for the kernel scalar argument.
2671  scalar_args = self.get_scalar_argument_referencesget_scalar_argument_references()
2672 
2673  # Create the PSyIR for the kernel:
2674  # proxy0%data(df) = MIN(ascalar, proxy0%data)
2675  lhs = arg_refs[0]
2676  rhs = IntrinsicCall.create(IntrinsicCall.Intrinsic.MIN,
2677  [scalar_args[0], lhs.copy()])
2678 
2679  # Create assignment and replace node
2680  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
2681 
2682 # ------------------------------------------------------------------- #
2683 # ============== Converting real to integer field elements ========== #
2684 # ------------------------------------------------------------------- #
2685 
2686 
2688  ''' Converts real-valued field elements to integer-valued
2689  field elements using the Fortran intrinsic `INT` function,
2690  `Y = INT(X, kind=i_<prec>)`. Here `Y` is an integer-valued
2691  field of precision `i_<prec>` and `X` is the real-valued
2692  field being converted.
2693 
2694  '''
2695  _datatype = "integer"
2696  _case_name = "real_to_int_X"
2697 
2698  @classmethod
2699  def metadata(cls):
2700  '''Returns the kernel metadata describing this built-in.
2701 
2702  :returns: kernel metadata describing this built-in.
2703  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
2704 
2705  '''
2706  return cls._builtin_metadata_builtin_metadata([
2707  FieldArgMetadata("gh_integer", "gh_write", "any_space_1"),
2708  FieldArgMetadata("gh_real", "gh_read", "any_space_1")])
2709 
2710  def __str__(self):
2711  return (f"Built-in: {self._case_name} (convert a real-valued to "
2712  f"an integer-valued field)")
2713 
2715  '''
2716  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
2717  This BuiltIn node is replaced by an Assignment node.
2718 
2719  :returns: the lowered version of this node.
2720  :rtype: :py:class:`psyclone.psyir.node.Node`
2721 
2722  '''
2723  # Get indexed references for each of the field (proxy) arguments.
2724  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
2725 
2726  # Create the PSyIR for the kernel:
2727  # proxy0%data(df) = INT(proxy1%data, kind=i_<prec>)
2728  lhs = arg_refs[0]
2729  i_precision = arg_refs[0].datatype.precision
2730  rhs = IntrinsicCall.create(
2731  IntrinsicCall.Intrinsic.INT,
2732  [arg_refs[1], ("kind", Reference(i_precision))])
2733 
2734  # Create assignment and replace node
2735  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
2736 
2737 
2738 # ------------------------------------------------------------------- #
2739 # ============== Converting real to real field elements ============= #
2740 # ------------------------------------------------------------------- #
2741 
2743  ''' Converts real-valued field elements to real-valued field elements
2744  of a different precision using the Fortran intrinsic `REAL` function,
2745  `Y = REAL(X, kind=r_<prec>)`. Here `Y` is a real-valued field of
2746  precision `kind=r_<prec>` and `X` is the real-valued field whose
2747  values are to be converted from their defined precision.
2748 
2749  '''
2750  _datatype = "real"
2751  _case_name = "real_to_real_X"
2752 
2753  @classmethod
2754  def metadata(cls):
2755  '''Returns the kernel metadata describing this built-in.
2756 
2757  :returns: kernel metadata describing this built-in.
2758  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
2759 
2760  '''
2761  return cls._builtin_metadata_builtin_metadata([
2762  FieldArgMetadata("gh_real", "gh_write", "any_space_1"),
2763  FieldArgMetadata("gh_real", "gh_read", "any_space_1")])
2764 
2765  def __str__(self):
2766  return (f"Built-in: {self._case_name} (convert a real-valued "
2767  f"to a real-valued field)")
2768 
2770  '''
2771  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
2772  This BuiltIn node is replaced by an Assignment node.
2773 
2774  :returns: the lowered version of this node.
2775  :rtype: :py:class:`psyclone.psyir.node.Node`
2776 
2777  '''
2778  # Get indexed references for each of the field (proxy) arguments.
2779  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
2780 
2781  # Create the PSyIR for the kernel:
2782  # proxy0%data(df) = REAL(proxy1%data, kind=r_<prec>)
2783  lhs = arg_refs[0]
2784  r_precision = arg_refs[0].datatype.precision
2785  rhs = IntrinsicCall.create(
2786  IntrinsicCall.Intrinsic.REAL,
2787  [arg_refs[1], ("kind", Reference(r_precision))])
2788 
2789  # Create assignment and replace node
2790  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
2791 
2792 
2793 # ******************************************************************* #
2794 # ************** Built-ins for integer-valued fields **************** #
2795 # ******************************************************************* #
2796 
2797 # ------------------------------------------------------------------- #
2798 # ============== Adding integer fields ============================== #
2799 # ------------------------------------------------------------------- #
2800 
2802  ''' Add corresponding elements of two, integer-valued, fields, `X`
2803  and `Y`, and return the result as a third, integer-valued, field, `Z`.
2804  Inherits the `lower_to_language_level` method from the real-valued
2805  built-in equivalent `LFRicXPlusYKern`.
2806 
2807  '''
2808  _case_name = "int_X_plus_Y"
2809  _datatype = "integer"
2810 
2811 
2813  ''' Add each element of an integer-valued field, `X`, to the
2814  corresponding element of another integer-valued field, `Y`, and
2815  store the result back in `X`.
2816  Inherits the `lower_to_language_level` method from the real-valued
2817  built-in equivalent `LFRicIncXPlusYKern`.
2818 
2819  '''
2820  _case_name = "int_inc_X_plus_Y"
2821  _datatype = "integer"
2822 
2823 
2825  ''' Add an integer scalar value, `a`, to each element of an
2826  integer-valued field, `X`, and return the result as a second,
2827  integer-valued, field, `Y`.
2828  Inherits the `lower_to_language_level` method from the real-valued
2829  built-in equivalent `LFRicAPlusXKern`.
2830 
2831  '''
2832  _case_name = "int_a_plus_X"
2833  _datatype = "integer"
2834 
2835 
2837  ''' Add an integer scalar value, `a`, to each element of an
2838  integer-valued field, `X`, and return the result in the
2839  same field.
2840  Inherits the `lower_to_language_level` method from the real-valued
2841  built-in equivalent `LFRicIncAPlusXKern`.
2842 
2843  '''
2844  _case_name = "int_inc_a_plus_X"
2845  _datatype = "integer"
2846 
2847 
2848 # ------------------------------------------------------------------- #
2849 # ============== Subtracting integer fields ========================= #
2850 # ------------------------------------------------------------------- #
2851 
2852 
2854  ''' Subtract each element of an integer-valued field, `Y`, from
2855  the corresponding element of another, integer-valued, field, `X`,
2856  and return the result as a third, integer-valued, field, `Z`.
2857  Inherits the `lower_to_language_level` method from the real-valued
2858  built-in equivalent `LFRicXMinusYKern`.
2859 
2860  '''
2861  _case_name = "int_X_minus_Y"
2862  _datatype = "integer"
2863 
2864 
2866  ''' Subtract each element of an integer-valued field, `Y`, from
2867  the corresponding element of another, integer-valued, field, `X`,
2868  and store the result back in `X`.
2869  Inherits the `lower_to_language_level` method from the real-valued
2870  built-in equivalent `LFRicIncXMinusYKern`.
2871 
2872  '''
2873  _case_name = "int_inc_X_minus_Y"
2874  _datatype = "integer"
2875 
2876 
2878  ''' Subtract each element of an integer-valued field, `X`, from
2879  an integer scalar value, `a`, and return the result as a second,
2880  integer-valued, field, `Y`.
2881  Inherits the `lower_to_language_level` method from the real-valued
2882  built-in equivalent `LFRicAMinusXKern`.
2883 
2884  '''
2885  _case_name = "int_a_minus_X"
2886  _datatype = "integer"
2887 
2888 
2890  ''' Subtract each element of an integer-valued field, `X`, from
2891  an integer scalar value, `a`, and return the result in the
2892  same field.
2893  Inherits the `lower_to_language_level` method from the real-valued
2894  built-in equivalent `LFRicIncAMinusXKern`.
2895 
2896  '''
2897  _case_name = "int_inc_a_minus_X"
2898  _datatype = "integer"
2899 
2900 
2902  ''' Subtract an integer scalar value, `a`, from each element of an
2903  integer-valued field, `X`, and return the result as a second,
2904  integer-valued, field, `Y`.
2905  Inherits the `lower_to_language_level` method from the real-valued
2906  built-in equivalent `LFRicXMinusAKern`.
2907 
2908  '''
2909  _case_name = "int_X_minus_a"
2910  _datatype = "integer"
2911 
2912 
2914  ''' Subtract an integer scalar value, `a`, from each element of an
2915  integer-valued field, `X`, and return the result in the same field.
2916  Inherits the `lower_to_language_level` method from the real-valued
2917  built-in equivalent `LFRicIncXMinusAKern`.
2918 
2919  '''
2920  _case_name = "int_inc_X_minus_a"
2921  _datatype = "integer"
2922 
2923 
2924 # ------------------------------------------------------------------- #
2925 # ============== Multiplying integer fields ========================= #
2926 # ------------------------------------------------------------------- #
2927 
2928 
2930  ''' Multiply each element of one, integer-valued, field, `X`, by
2931  the corresponding element of another, integer-valued, field, `Y`,
2932  and return the result as a third, integer-valued, field, `Z`.
2933  Inherits the `lower_to_language_level` method from the real-valued
2934  built-in equivalent `LFRicXTimesYKern`.
2935 
2936  '''
2937  _case_name = "int_X_times_Y"
2938  _datatype = "integer"
2939 
2940 
2942  ''' Multiply each element of one, integer-valued, field, `X`, by
2943  the corresponding element of another, integer-valued, field, `Y`,
2944  and store the result back in `X`.
2945  Inherits the `lower_to_language_level` method from the real-valued
2946  built-in equivalent `LFRicIncXTimesYKern`.
2947 
2948  '''
2949  _case_name = "int_inc_X_times_Y"
2950  _datatype = "integer"
2951 
2952 
2953 # ------------------------------------------------------------------- #
2954 # ============== Scaling integer fields ============================= #
2955 # ------------------------------------------------------------------- #
2956 
2957 
2959  ''' Multiply each element of the first, integer-valued, field, `X`,
2960  by an integer scalar, `a`, and return the result as a second,
2961  integer-valued, field `Y` (`Y = a*X`).
2962  Inherits the `lower_to_language_level` method from the real-valued
2963  built-in equivalent `LFRicATimesXKern`.
2964 
2965  '''
2966  _case_name = "int_a_times_X"
2967  _datatype = "integer"
2968 
2969 
2971  ''' Multiply each element of an integer-valued field, `X` by
2972  an integer scalar, `a`, and store the result back in `X`.
2973  Inherits the `lower_to_language_level` method from the real-valued
2974  built-in equivalent `LFRicIncATimesXKern`.
2975 
2976  '''
2977  _case_name = "int_inc_a_times_X"
2978  _datatype = "integer"
2979 
2980 
2981 # ------------------------------------------------------------------- #
2982 # ============== Setting integer field elements to a value ========= #
2983 # ------------------------------------------------------------------- #
2984 
2985 
2987  ''' Assign a single constant integer scalar value, `c`, to all
2988  elements of an integer-valued field, `X`.
2989  Inherits the `lower_to_language_level` method from the real-valued
2990  built-in equivalent `LFRicSetvalCKern`.
2991 
2992  '''
2993  _case_name = "int_setval_c"
2994  _datatype = "integer"
2995 
2996 
2998  ''' Copy one element of an integer-valued field (second argument),
2999  `X`, to the corresponding element of another, integer-valued,
3000  field (first argument), `Y`.
3001  Inherits the `lower_to_language_level` method from the real-valued
3002  built-in equivalent `LFRicSetvalXKern`.
3003 
3004  '''
3005  _case_name = "int_setval_X"
3006  _datatype = "integer"
3007 
3008 
3009 # ------------------------------------------------------------------- #
3010 # ============== Sign of integer field elements ===================== #
3011 # ------------------------------------------------------------------- #
3012 
3013 
3015  ''' Returns the sign of an integer-valued field elements using the
3016  Fortran intrinsic `sign` function, `Y = sign(a, X)`.
3017  Inherits the `lower_to_language_level` method from the real-valued
3018  built-in equivalent `LFRicSignXKern`.
3019 
3020  '''
3021  _case_name = "int_sign_X"
3022  _datatype = "integer"
3023 
3024 
3025 # ------------------------------------------------------------------- #
3026 # ======== Maximum of (integer scalar, integer field elements) ====== #
3027 # ------------------------------------------------------------------- #
3028 
3029 
3031  ''' Returns the maximum of an integer scalar and integer-valued
3032  field elements. The result is stored as another, integer-valued,
3033  field: `Y = max(a, X)`.
3034  Inherits the `lower_to_language_level` method from the real-valued
3035  built-in equivalent `LFRicMaxAXKern`.
3036  '''
3037  _case_name = "int_max_aX"
3038  _datatype = "integer"
3039 
3040 
3042  ''' Returns the maximum of an integer scalar and integer-valued
3043  field elements. The result is stored in the same, integer-valued,
3044  field: `X = max(a, X)`.
3045  Inherits the `lower_to_language_level` method from the real-valued
3046  built-in equivalent `LFRicIncMaxAXKern`.
3047  '''
3048  _case_name = "int_inc_max_aX"
3049  _datatype = "integer"
3050 
3051 
3052 # ------------------------------------------------------------------- #
3053 # ======== Minimum of (integer scalar, integer field elements) ====== #
3054 # ------------------------------------------------------------------- #
3055 
3056 
3058  ''' Returns the minimum of an integer scalar and integer-valued
3059  field elements. The result is stored as another, integer-valued,
3060  field: `Y = min(a, X)`.
3061  Inherits the `lower_to_language_level` method from the real-valued
3062  built-in equivalent `LFRicMinAXKern`.
3063 
3064  '''
3065  _case_name = "int_min_aX"
3066  _datatype = "integer"
3067 
3068 
3070  ''' Returns the minimum of an integer scalar and integer-valued
3071  field elements. The result is stored in the same, integer-valued,
3072  field: `X = min(a, X)`.
3073  Inherits the `lower_to_language_level` method from the real-valued
3074  built-in equivalent `LFRicIncMinAXKern`.
3075 
3076  '''
3077  _case_name = "int_inc_min_aX"
3078  _datatype = "integer"
3079 
3080 
3081 # ------------------------------------------------------------------- #
3082 # ============== Converting integer to real field elements ========== #
3083 # ------------------------------------------------------------------- #
3084 
3086  ''' Converts integer-valued field elements to real-valued
3087  field elements using the Fortran intrinsic `REAL` function,
3088  `Y = REAL(X, kind=r_<prec>)`. Here `Y` is a real-valued
3089  field of precision `r_<prec>` and `X` is the integer-valued
3090  field being converted.
3091 
3092  '''
3093  _datatype = "real"
3094  _case_name = "int_to_real_X"
3095 
3096  @classmethod
3097  def metadata(cls):
3098  '''Returns the kernel metadata describing this built-in.
3099 
3100  :returns: kernel metadata describing this built-in.
3101  :rtype: :py:class:`psyclone.domain.lfric.kernel.LFRicKernelMetadata`
3102 
3103  '''
3104  return cls._builtin_metadata_builtin_metadata([
3105  FieldArgMetadata("gh_real", "gh_write", "any_space_1"),
3106  FieldArgMetadata("gh_integer", "gh_read", "any_space_1")])
3107 
3108  def __str__(self):
3109  return (f"Built-in: {self._case_name} (convert an integer-valued "
3110  f"to a real-valued field)")
3111 
3113  '''
3114  Lowers this LFRic-specific built-in kernel to language-level PSyIR.
3115  This BuiltIn node is replaced by an Assignment node.
3116 
3117  :returns: the lowered version of this node.
3118  :rtype: :py:class:`psyclone.psyir.node.Node`
3119 
3120  '''
3121  # Get indexed references for each of the field (proxy) arguments.
3122  arg_refs = self.get_indexed_field_argument_referencesget_indexed_field_argument_references()
3123 
3124  # Create the PSyIR for the kernel:
3125  # proxy0%data(df) = REAL(proxy1%data, kind=r_<prec>)
3126  lhs = arg_refs[0]
3127  r_precision = arg_refs[0].datatype.precision
3128  rhs = IntrinsicCall.create(
3129  IntrinsicCall.Intrinsic.REAL,
3130  [arg_refs[1], ("kind", Reference(r_precision))])
3131 
3132  # Create assignment and replace node
3133  return self._replace_with_assignment_replace_with_assignment(lhs, rhs)
3134 
3135 
3136 # The built-in operations that we support for this API. The meta-data
3137 # describing these kernels is in lfric_builtins_mod.f90. This dictionary
3138 # can only be defined after all of the necessary 'class' statements have
3139 # been executed (happens when this module is imported into another).
3140 # Built-ins for real-valued fields
3141 REAL_BUILTIN_MAP_CAPITALISED = {
3142  # Adding (scaled) real fields
3143  "X_plus_Y": LFRicXPlusYKern,
3144  "inc_X_plus_Y": LFRicIncXPlusYKern,
3145  "a_plus_X": LFRicAPlusXKern,
3146  "inc_a_plus_X": LFRicIncAPlusXKern,
3147  "aX_plus_Y": LFRicAXPlusYKern,
3148  "inc_aX_plus_Y": LFRicIncAXPlusYKern,
3149  "inc_X_plus_bY": LFRicIncXPlusBYKern,
3150  "aX_plus_bY": LFRicAXPlusBYKern,
3151  "inc_aX_plus_bY": LFRicIncAXPlusBYKern,
3152  "aX_plus_aY": LFRicAXPlusAYKern,
3153  # Subtracting (scaled) real fields
3154  "X_minus_Y": LFRicXMinusYKern,
3155  "inc_X_minus_Y": LFRicIncXMinusYKern,
3156  "a_minus_X": LFRicAMinusXKern,
3157  "inc_a_minus_X": LFRicIncAMinusXKern,
3158  "X_minus_a": LFRicXMinusAKern,
3159  "inc_X_minus_a": LFRicIncXMinusAKern,
3160  "aX_minus_Y": LFRicAXMinusYKern,
3161  "X_minus_bY": LFRicXMinusBYKern,
3162  "inc_X_minus_bY": LFRicIncXMinusBYKern,
3163  "aX_minus_bY": LFRicAXMinusBYKern,
3164  # Multiplying (scaled) real fields
3165  "X_times_Y": LFRicXTimesYKern,
3166  "inc_X_times_Y": LFRicIncXTimesYKern,
3167  "inc_aX_times_Y": LFRicIncAXTimesYKern,
3168  # Multiplying real fields by a real scalar (scaling fields)
3169  "a_times_X": LFRicATimesXKern,
3170  "inc_a_times_X": LFRicIncATimesXKern,
3171  # Dividing real fields
3172  "X_divideby_Y": LFRicXDividebyYKern,
3173  "inc_X_divideby_Y": LFRicIncXDividebyYKern,
3174  "X_divideby_a": LFRicXDividebyAKern,
3175  "inc_X_divideby_a": LFRicIncXDividebyAKern,
3176  # Dividing a real scalar by elements of a real field
3177  # (inverse scaling of fields)
3178  "a_divideby_X": LFRicADividebyXKern,
3179  "inc_a_divideby_X": LFRicIncADividebyXKern,
3180  # Raising a real field to a scalar
3181  "inc_X_powreal_a": LFRicIncXPowrealAKern,
3182  "inc_X_powint_n": LFRicIncXPowintNKern,
3183  # Setting real field elements to scalar or other
3184  # real field's values
3185  "setval_c": LFRicSetvalCKern,
3186  "setval_X": LFRicSetvalXKern,
3187  "setval_random": LFRicSetvalRandomKern,
3188  # Inner product of real fields
3189  "X_innerproduct_Y": LFRicXInnerproductYKern,
3190  "X_innerproduct_X": LFRicXInnerproductXKern,
3191  # Sum values of a real field
3192  "sum_X": LFRicSumXKern,
3193  # Sign of real field elements applied to a scalar value
3194  "sign_X": LFRicSignXKern,
3195  # Maximum of a real scalar value and real field elements
3196  "max_aX": LFRicMaxAXKern,
3197  "inc_max_aX": LFRicIncMaxAXKern,
3198  # Minimum of a real scalar value and real field elements
3199  "min_aX": LFRicMinAXKern,
3200  "inc_min_aX": LFRicIncMinAXKern,
3201  # Converting real to integer field elements
3202  "real_to_int_X": LFRicRealToIntXKern,
3203  # Converting real to real field elements
3204  "real_to_real_X": LFRicRealToRealXKern}
3205 
3206 # Built-ins for integer-valued fields
3207 INT_BUILTIN_MAP_CAPITALISED = {
3208  # Adding integer fields
3209  "int_X_plus_Y": LFRicIntXPlusYKern,
3210  "int_inc_X_plus_Y": LFRicIntIncXPlusYKern,
3211  "int_a_plus_X": LFRicIntAPlusXKern,
3212  "int_inc_a_plus_X": LFRicIntIncAPlusXKern,
3213  # Subtracting integer fields
3214  "int_X_minus_Y": LFRicIntXMinusYKern,
3215  "int_inc_X_minus_Y": LFRicIntIncXMinusYKern,
3216  "int_a_minus_X": LFRicIntAMinusXKern,
3217  "int_inc_a_minus_X": LFRicIntIncAMinusXKern,
3218  "int_X_minus_a": LFRicIntXMinusAKern,
3219  "int_inc_X_minus_a": LFRicIntIncXMinusAKern,
3220  # Multiplying (scaled) real fields
3221  "int_X_times_Y": LFRicIntXTimesYKern,
3222  "int_inc_X_times_Y": LFRicIntIncXTimesYKern,
3223  # Multiplying integer fields by an integer scalar (scaling fields)
3224  "int_a_times_X": LFRicIntATimesXKern,
3225  "int_inc_a_times_X": LFRicIntIncATimesXKern,
3226  # Setting an integer field elements to an integer scalar
3227  # or other integer field's values
3228  "int_setval_c": LFRicIntSetvalCKern,
3229  "int_setval_X": LFRicIntSetvalXKern,
3230  # Sign of integer field elements applied to a scalar value
3231  "int_sign_X": LFRicIntSignXKern,
3232  # Maximum of an integer scalar value and integer field elements
3233  "int_max_aX": LFRicIntMaxAXKern,
3234  "int_inc_max_aX": LFRicIntIncMaxAXKern,
3235  # Minimum of an integer scalar value and integer field elements
3236  "int_min_aX": LFRicIntMinAXKern,
3237  "int_inc_min_aX": LFRicIntIncMinAXKern,
3238  # Converting integer to real field elements
3239  "int_to_real_X": LFRicIntToRealXKern}
3240 
3241 # Built-in map dictionary for all built-ins
3242 BUILTIN_MAP_CAPITALISED = REAL_BUILTIN_MAP_CAPITALISED
3243 BUILTIN_MAP_CAPITALISED.update(INT_BUILTIN_MAP_CAPITALISED)
3244 
3245 # Built-in map dictionary in lowercase keys for invoke generation and
3246 # comparison purposes. This does not enforce case sensitivity to Fortran
3247 # built-in names.
3248 BUILTIN_MAP = get_lowercase_builtin_map(BUILTIN_MAP_CAPITALISED)
3249 
3250 
3251 # For AutoAPI documentation generation.
3252 __all__ = ['LFRicBuiltInCallFactory',
3253  'LFRicBuiltIn',
3254  'LFRicXPlusYKern',
3255  'LFRicIncXPlusYKern',
3256  'LFRicAPlusXKern',
3257  'LFRicIncAPlusXKern',
3258  'LFRicAXPlusYKern',
3259  'LFRicIncAXPlusYKern',
3260  'LFRicIncXPlusBYKern',
3261  'LFRicAXPlusBYKern',
3262  'LFRicIncAXPlusBYKern',
3263  'LFRicAXPlusAYKern',
3264  'LFRicXMinusYKern',
3265  'LFRicIncXMinusYKern',
3266  'LFRicAMinusXKern',
3267  'LFRicIncAMinusXKern',
3268  'LFRicXMinusAKern',
3269  'LFRicIncXMinusAKern',
3270  'LFRicAXMinusYKern',
3271  'LFRicXMinusBYKern',
3272  'LFRicIncXMinusBYKern',
3273  'LFRicAXMinusBYKern',
3274  'LFRicXTimesYKern',
3275  'LFRicIncXTimesYKern',
3276  'LFRicIncAXTimesYKern',
3277  'LFRicATimesXKern',
3278  'LFRicIncATimesXKern',
3279  'LFRicXDividebyYKern',
3280  'LFRicIncXDividebyYKern',
3281  'LFRicXDividebyAKern',
3282  'LFRicIncXDividebyAKern',
3283  'LFRicADividebyXKern',
3284  'LFRicIncADividebyXKern',
3285  'LFRicIncXPowrealAKern',
3286  'LFRicIncXPowintNKern',
3287  'LFRicSetvalCKern',
3288  'LFRicSetvalXKern',
3289  'LFRicSetvalRandomKern',
3290  'LFRicXInnerproductYKern',
3291  'LFRicXInnerproductXKern',
3292  'LFRicSumXKern',
3293  'LFRicSignXKern',
3294  'LFRicMaxAXKern',
3295  'LFRicIncMaxAXKern',
3296  'LFRicMinAXKern',
3297  'LFRicIncMinAXKern',
3298  'LFRicRealToIntXKern',
3299  'LFRicRealToRealXKern',
3300  'LFRicIntXPlusYKern',
3301  'LFRicIntIncXPlusYKern',
3302  'LFRicIntAPlusXKern',
3303  'LFRicIntIncAPlusXKern',
3304  'LFRicIntXMinusYKern',
3305  'LFRicIntIncXMinusYKern',
3306  'LFRicIntAMinusXKern',
3307  'LFRicIntIncAMinusXKern',
3308  'LFRicIntXMinusAKern',
3309  'LFRicIntIncXMinusAKern',
3310  'LFRicIntXTimesYKern',
3311  'LFRicIntIncXTimesYKern',
3312  'LFRicIntATimesXKern',
3313  'LFRicIntIncATimesXKern',
3314  'LFRicIntSetvalCKern',
3315  'LFRicIntSetvalXKern',
3316  'LFRicIntSignXKern',
3317  'LFRicIntMaxAXKern',
3318  'LFRicIntIncMaxAXKern',
3319  'LFRicIntMinAXKern',
3320  'LFRicIntIncMinAXKern',
3321  'LFRicIntToRealXKern']
def name(self, value)
Definition: psyGen.py:1321
def arg_descriptors(self, obj)
Definition: psyGen.py:1305
def name(self)
Definition: psyGen.py:1313
def args(self)
Definition: psyGen.py:1080
def arg_descriptors(self)
Definition: psyGen.py:1301
def _reduction_reference(self)
Definition: psyGen.py:1265
def iterates_over(self)
Definition: psyGen.py:1343