Reference Guide  2.5.0
psyclone.transformations.Dynamo0p3KernelConstTrans Class Reference
Inheritance diagram for psyclone.transformations.Dynamo0p3KernelConstTrans:
Collaboration diagram for psyclone.transformations.Dynamo0p3KernelConstTrans:

Public Member Functions

def __str__ (self)
 
def name (self)
 
def apply (self, node, options=None)
 
def validate (self, node, options=None)
 

Static Public Attributes

dictionary space_to_dofs
 

Detailed Description

Modifies a kernel so that the number of dofs, number of layers and
number of quadrature points are fixed in the kernel rather than
being passed in by argument.

>>> from psyclone.parse.algorithm import parse
>>> from psyclone.psyGen import PSyFactory
>>> api = "dynamo0.3"
>>> ast, invokeInfo = parse("file.f90", api=api)
>>> psy=PSyFactory(api).create(invokeInfo)
>>> schedule = psy.invokes.get('invoke_0').schedule
>>> # Uncomment the following line to see a text view of the schedule
>>> # print(schedule.view())
>>>
>>> from psyclone.transformations import Dynamo0p3KernelConstTrans
>>> trans = Dynamo0p3KernelConstTrans()
>>> for kernel in schedule.coded_kernels():
>>>     trans.apply(kernel, number_of_layers=150)
>>>     kernel_schedule = kernel.get_kernel_schedule()
>>>     # Uncomment the following line to see a text view of the
>>>     # symbol table
>>>     # print(kernel_schedule.symbol_table.view())

Definition at line 2076 of file transformations.py.

Member Function Documentation

◆ apply()

def psyclone.transformations.Dynamo0p3KernelConstTrans.apply (   self,
  node,
  options = None 
)
Transforms a kernel so that the values for the number of degrees of
freedom (if a valid value for the element_order arg is
provided), the number of quadrature points (if the quadrature
arg is set to True) and the number of layers (if a valid value
for the number_of_layers arg is provided) are constant in a
kernel rather than being passed in by argument.

The "cellshape", "element_order" and "number_of_layers"
arguments are provided to mirror the namelist values that are
input into an LFRic model when it is run.

Quadrature support is currently limited to XYoZ in ths
transformation. In the case of XYoZ the number of quadrature
points (for horizontal and vertical) are set to the
element_order + 3 in the LFRic infrastructure so their value
is derived.

:param node: a kernel node.
:type node: :py:obj:`psyclone.domain.lfric.LFRicKern`
:param options: a dictionary with options for transformations.
:type options: Optional[Dict[str, Any]]
:param str options["cellshape"]: the shape of the cells. This is\
    provided as it helps determine the number of dofs a field has\
    for a particular function space. Currently only "quadrilateral"\
    is supported which is also the default value.
:param int options["element_order"]: the order of the cell. In \
    combination with cellshape, this determines the number of \
    dofs a field has for a particular function space. If it is set \
    to None (the default) then the dofs values are not set as \
    constants in the kernel, otherwise they are.
:param int options["number_of_layers"]: the number of vertical \
    layers in the LFRic model mesh used for this particular run. If \
    this is set to None (the default) then the nlayers value is not \
    set as a constant in the kernel, otherwise it is.
:param bool options["quadrature"]: whether the number of quadrature \
    points values are set as constants in the kernel (True) or not \
    (False). The default is False.

Reimplemented from psyclone.psyGen.Transformation.

Definition at line 2138 of file transformations.py.

2138  def apply(self, node, options=None):
2139  # pylint: disable=too-many-statements, too-many-locals
2140  '''Transforms a kernel so that the values for the number of degrees of
2141  freedom (if a valid value for the element_order arg is
2142  provided), the number of quadrature points (if the quadrature
2143  arg is set to True) and the number of layers (if a valid value
2144  for the number_of_layers arg is provided) are constant in a
2145  kernel rather than being passed in by argument.
2146 
2147  The "cellshape", "element_order" and "number_of_layers"
2148  arguments are provided to mirror the namelist values that are
2149  input into an LFRic model when it is run.
2150 
2151  Quadrature support is currently limited to XYoZ in ths
2152  transformation. In the case of XYoZ the number of quadrature
2153  points (for horizontal and vertical) are set to the
2154  element_order + 3 in the LFRic infrastructure so their value
2155  is derived.
2156 
2157  :param node: a kernel node.
2158  :type node: :py:obj:`psyclone.domain.lfric.LFRicKern`
2159  :param options: a dictionary with options for transformations.
2160  :type options: Optional[Dict[str, Any]]
2161  :param str options["cellshape"]: the shape of the cells. This is\
2162  provided as it helps determine the number of dofs a field has\
2163  for a particular function space. Currently only "quadrilateral"\
2164  is supported which is also the default value.
2165  :param int options["element_order"]: the order of the cell. In \
2166  combination with cellshape, this determines the number of \
2167  dofs a field has for a particular function space. If it is set \
2168  to None (the default) then the dofs values are not set as \
2169  constants in the kernel, otherwise they are.
2170  :param int options["number_of_layers"]: the number of vertical \
2171  layers in the LFRic model mesh used for this particular run. If \
2172  this is set to None (the default) then the nlayers value is not \
2173  set as a constant in the kernel, otherwise it is.
2174  :param bool options["quadrature"]: whether the number of quadrature \
2175  points values are set as constants in the kernel (True) or not \
2176  (False). The default is False.
2177 
2178  '''
2179  # --------------------------------------------------------------------
2180  def make_constant(symbol_table, arg_position, value,
2181  function_space=None):
2182  '''Utility function that modifies the argument at position
2183  'arg_position' into a compile-time constant with value
2184  'value'.
2185 
2186  :param symbol_table: the symbol table for the kernel holding
2187  the argument that is going to be modified.
2188  :type symbol_table: :py:class:`psyclone.psyir.symbols.SymbolTable`
2189  :param int arg_position: the argument's position in the
2190  argument list.
2191  :param value: the constant value that this argument is going to
2192  be given. Its type depends on the type of the argument.
2193  :type value: int, str or bool
2194  :type str function_space: the name of the function space if there
2195  is a function space associated with this argument. Defaults
2196  to None.
2197 
2198  '''
2199  arg_index = arg_position - 1
2200  try:
2201  symbol = symbol_table.argument_list[arg_index]
2202  except IndexError as err:
2203  raise TransformationError(
2204  f"The argument index '{arg_index}' is greater than the "
2205  f"number of arguments "
2206  f"'{len(symbol_table.argument_list)}'.") from err
2207  # Perform some basic checks on the argument to make sure
2208  # it is the expected type
2209  if not isinstance(symbol.datatype, ScalarType):
2210  raise TransformationError(
2211  f"Expected entry to be a scalar argument but found "
2212  f"'{type(symbol.datatype).__name__}'.")
2213  if symbol.datatype.intrinsic != ScalarType.Intrinsic.INTEGER:
2214  raise TransformationError(
2215  f"Expected entry to be a scalar integer argument "
2216  f"but found '{symbol.datatype}'.")
2217  if symbol.is_constant:
2218  raise TransformationError(
2219  "Expected entry to be a scalar integer argument "
2220  "but found a constant.")
2221 
2222  # Create a new symbol with a known constant value then swap
2223  # it with the argument. The argument then becomes xxx_dummy
2224  # and is unused within the kernel body.
2225  orig_name = symbol.name
2226  new_name = symbol_table.next_available_name(f"{orig_name}_dummy")
2227  local_symbol = DataSymbol(new_name, INTEGER_TYPE,
2228  is_constant=True, initial_value=value)
2229  symbol_table.add(local_symbol)
2230  symbol_table.swap_symbol_properties(symbol, local_symbol)
2231 
2232  if function_space:
2233  print(f" Modified {orig_name}, arg position {arg_position},"
2234  f" function space {function_space}, value {value}.")
2235  else:
2236  print(f" Modified {orig_name}, arg position {arg_position},"
2237  f" value {value}.")
2238  # --------------------------------------------------------------------
2239 
2240  self.validate(node, options)
2241 
2242  if not options:
2243  options = {}
2244  number_of_layers = options.get("number_of_layers", None)
2245  quadrature = options.get("quadrature", False)
2246  element_order = options.get("element_order", None)
2247  kernel = node
2248 
2249  arg_list_info = KernCallArgList(kernel)
2250  arg_list_info.generate()
2251  try:
2252  kernel_schedule = kernel.get_kernel_schedule()
2253  except NotImplementedError as excinfo:
2254  raise TransformationError(
2255  f"Failed to parse kernel '{kernel.name}'. Error reported was "
2256  f"'{excinfo}'.") from excinfo
2257 
2258  symbol_table = kernel_schedule.symbol_table
2259  if number_of_layers:
2260  make_constant(symbol_table, arg_list_info.nlayers_positions[0],
2261  number_of_layers)
2262 
2263  if quadrature and arg_list_info.nqp_positions:
2264  # TODO #705 - support the transformation of kernels requiring
2265  # other quadrature types (face/edge, multiple).
2266  if kernel.eval_shapes == ["gh_quadrature_xyoz"]:
2267  make_constant(symbol_table,
2268  arg_list_info.nqp_positions[0]["horizontal"],
2269  element_order+3)
2270  make_constant(symbol_table,
2271  arg_list_info.nqp_positions[0]["vertical"],
2272  element_order+3)
2273  else:
2274  raise TransformationError(
2275  f"Error in Dynamo0p3KernelConstTrans transformation. "
2276  f"Support is currently limited to 'xyoz' quadrature but "
2277  f"found {kernel.eval_shapes}.")
2278 
2279  const = LFRicConstants()
2280  if element_order is not None:
2281  # Modify the symbol table for degrees of freedom here.
2282  for info in arg_list_info.ndf_positions:
2283  if (info.function_space.lower() in
2284  (const.VALID_ANY_SPACE_NAMES +
2285  const.VALID_ANY_DISCONTINUOUS_SPACE_NAMES +
2286  ["any_w2"])):
2287  # skip any_space_*, any_discontinuous_space_* and any_w2
2288  print(f" Skipped dofs, arg position {info.position}, "
2289  f"function space {info.function_space}")
2290  else:
2291  try:
2292  ndofs = Dynamo0p3KernelConstTrans. \
2293  space_to_dofs[
2294  info.function_space](element_order)
2295  except KeyError as err:
2296  raise InternalError(
2297  f"Error in Dynamo0p3KernelConstTrans "
2298  f"transformation. Unsupported function space "
2299  f"'{info.function_space}' found. Expecting one of "
2300  f"""{Dynamo0p3KernelConstTrans.
2301  space_to_dofs.keys()}.""") from err
2302  make_constant(symbol_table, info.position, ndofs,
2303  function_space=info.function_space)
2304 
2305  # Flag that the kernel has been modified
2306  kernel.modified = True
2307 

References psyclone.domain.lfric.kernel.lfric_kernel_metadata.LFRicKernelMetadata.validate(), psyclone.transformations.MoveTrans.validate(), psyclone.transformations.Dynamo0p3AsyncHaloExchangeTrans.validate(), psyclone.domain.common.transformations.alg_invoke_2_psy_call_trans.AlgInvoke2PSyCallTrans.validate(), psyclone.domain.common.transformations.alg_trans.AlgTrans.validate(), psyclone.domain.common.transformations.kernel_module_inline_trans.KernelModuleInlineTrans.validate(), psyclone.domain.common.transformations.raise_psyir_2_alg_trans.RaisePSyIR2AlgTrans.validate(), psyclone.domain.gocean.transformations.gocean_const_loop_bounds_trans.GOConstLoopBoundsTrans.validate(), psyclone.domain.gocean.transformations.gocean_move_iteration_boundaries_inside_kernel_trans.GOMoveIterationBoundariesInsideKernelTrans.validate(), psyclone.domain.gocean.transformations.gocean_opencl_trans.GOOpenCLTrans.validate(), psyclone.domain.gocean.transformations.raise_psyir_2_gocean_kern_trans.RaisePSyIR2GOceanKernTrans.validate(), psyclone.domain.lfric.transformations.lfric_alg_invoke_2_psy_call_trans.LFRicAlgInvoke2PSyCallTrans.validate(), psyclone.domain.lfric.transformations.raise_psyir_2_lfric_kern_trans.RaisePSyIR2LFRicKernTrans.validate(), psyclone.domain.nemo.transformations.create_nemo_invoke_schedule_trans.CreateNemoInvokeScheduleTrans.validate(), psyclone.domain.nemo.transformations.create_nemo_psy_trans.CreateNemoPSyTrans.validate(), psyclone.domain.nemo.transformations.nemo_allarrayrange2loop_trans.NemoAllArrayRange2LoopTrans.validate(), psyclone.domain.nemo.transformations.nemo_arrayrange2loop_trans.NemoArrayRange2LoopTrans.validate(), psyclone.domain.nemo.transformations.nemo_outerarrayrange2loop_trans.NemoOuterArrayRange2LoopTrans.validate(), psyclone.psyad.transformations.assignment_trans.AssignmentTrans.validate(), psyclone.psyGen.Transformation.validate(), psyclone.psyir.transformations.acc_update_trans.ACCUpdateTrans.validate(), psyclone.psyir.transformations.allarrayaccess2loop_trans.AllArrayAccess2LoopTrans.validate(), psyclone.psyir.transformations.arrayaccess2loop_trans.ArrayAccess2LoopTrans.validate(), psyclone.psyir.transformations.arrayrange2loop_trans.ArrayRange2LoopTrans.validate(), psyclone.psyir.transformations.chunk_loop_trans.ChunkLoopTrans.validate(), psyclone.psyir.transformations.fold_conditional_return_expressions_trans.FoldConditionalReturnExpressionsTrans.validate(), psyclone.psyir.transformations.hoist_local_arrays_trans.HoistLocalArraysTrans.validate(), psyclone.psyir.transformations.hoist_loop_bound_expr_trans.HoistLoopBoundExprTrans.validate(), psyclone.psyir.transformations.hoist_trans.HoistTrans.validate(), psyclone.psyir.transformations.inline_trans.InlineTrans.validate(), psyclone.psyir.transformations.intrinsics.array_reduction_base_trans.ArrayReductionBaseTrans.validate(), psyclone.psyir.transformations.intrinsics.dotproduct2code_trans.DotProduct2CodeTrans.validate(), psyclone.psyir.transformations.intrinsics.intrinsic2code_trans.Intrinsic2CodeTrans.validate(), psyclone.psyir.transformations.intrinsics.matmul2code_trans.Matmul2CodeTrans.validate(), psyclone.psyir.transformations.loop_swap_trans.LoopSwapTrans.validate(), psyclone.psyir.transformations.loop_tiling_2d_trans.LoopTiling2DTrans.validate(), psyclone.psyir.transformations.loop_trans.LoopTrans.validate(), psyclone.psyir.transformations.omp_task_trans.OMPTaskTrans.validate(), psyclone.psyir.transformations.omp_taskwait_trans.OMPTaskwaitTrans.validate(), psyclone.psyir.transformations.parallel_loop_trans.ParallelLoopTrans.validate(), psyclone.psyir.transformations.reference2arrayrange_trans.Reference2ArrayRangeTrans.validate(), psyclone.psyir.transformations.replace_induction_variables_trans.ReplaceInductionVariablesTrans.validate(), psyclone.transformations.OMPDeclareTargetTrans.validate(), psyclone.transformations.DynamoOMPParallelLoopTrans.validate(), psyclone.transformations.Dynamo0p3OMPLoopTrans.validate(), psyclone.transformations.GOceanOMPLoopTrans.validate(), psyclone.transformations.Dynamo0p3RedundantComputationTrans.validate(), psyclone.transformations.Dynamo0p3KernelConstTrans.validate(), psyclone.transformations.ACCRoutineTrans.validate(), psyclone.transformations.KernelImportsToArguments.validate(), psyclone.domain.gocean.transformations.gocean_loop_fuse_trans.GOceanLoopFuseTrans.validate(), psyclone.domain.lfric.transformations.lfric_loop_fuse_trans.LFRicLoopFuseTrans.validate(), psyclone.psyir.transformations.loop_fuse_trans.LoopFuseTrans.validate(), psyclone.domain.gocean.transformations.gocean_extract_trans.GOceanExtractTrans.validate(), psyclone.domain.lfric.transformations.lfric_extract_trans.LFRicExtractTrans.validate(), psyclone.psyir.transformations.extract_trans.ExtractTrans.validate(), psyclone.psyir.transformations.nan_test_trans.NanTestTrans.validate(), psyclone.psyir.transformations.read_only_verify_trans.ReadOnlyVerifyTrans.validate(), psyclone.transformations.ParallelRegionTrans.validate(), psyclone.transformations.OMPParallelTrans.validate(), psyclone.transformations.ACCParallelTrans.validate(), psyclone.transformations.ACCKernelsTrans.validate(), psyclone.transformations.ACCDataTrans.validate(), psyclone.psyir.transformations.psy_data_trans.PSyDataTrans.validate(), psyclone.psyir.transformations.region_trans.RegionTrans.validate(), and psyclone.transformations.ACCEnterDataTrans.validate().

Here is the call graph for this function:

◆ name()

def psyclone.transformations.Dynamo0p3KernelConstTrans.name (   self)
:returns: the name of this transformation as a string.
:rtype: str

Reimplemented from psyclone.psyGen.Transformation.

Definition at line 2131 of file transformations.py.

2131  def name(self):
2132  '''
2133  :returns: the name of this transformation as a string.
2134  :rtype: str
2135  '''
2136  return "Dynamo0p3KernelConstTrans"
2137 
Here is the caller graph for this function:

◆ validate()

def psyclone.transformations.Dynamo0p3KernelConstTrans.validate (   self,
  node,
  options = None 
)
This method checks whether the input arguments are valid for
this transformation.

:param node: a dynamo 0.3 kernel node.
:type node: :py:obj:`psyclone.domain.lfric.LFRicKern`
:param options: a dictionary with options for transformations.
:type options: Optional[Dict[str, Any]]
:param str options["cellshape"]: the shape of the elements/cells.
:param int options["element_order"]: the order of the elements/cells.
:param int options["number_of_layers"]: the number of layers to use.
:param bool options["quadrature"]: whether quadrature dimension sizes \
    should or shouldn't be set as constants in a kernel.

:raises TransformationError: if the node argument is not a \
    dynamo 0.3 kernel, the cellshape argument is not set to \
    "quadrilateral", the element_order argument is not a 0 or a \
    positive integer, the number of layers argument is not a \
    positive integer, the quadrature argument is not a boolean, \
    neither element order nor number of layers arguments are set \
    (as the transformation would then do nothing), or the \
    quadrature argument is True but the element order is not \
    provided (as the former needs the latter).

Reimplemented from psyclone.psyGen.Transformation.

Definition at line 2308 of file transformations.py.

2308  def validate(self, node, options=None):
2309  '''This method checks whether the input arguments are valid for
2310  this transformation.
2311 
2312  :param node: a dynamo 0.3 kernel node.
2313  :type node: :py:obj:`psyclone.domain.lfric.LFRicKern`
2314  :param options: a dictionary with options for transformations.
2315  :type options: Optional[Dict[str, Any]]
2316  :param str options["cellshape"]: the shape of the elements/cells.
2317  :param int options["element_order"]: the order of the elements/cells.
2318  :param int options["number_of_layers"]: the number of layers to use.
2319  :param bool options["quadrature"]: whether quadrature dimension sizes \
2320  should or shouldn't be set as constants in a kernel.
2321 
2322  :raises TransformationError: if the node argument is not a \
2323  dynamo 0.3 kernel, the cellshape argument is not set to \
2324  "quadrilateral", the element_order argument is not a 0 or a \
2325  positive integer, the number of layers argument is not a \
2326  positive integer, the quadrature argument is not a boolean, \
2327  neither element order nor number of layers arguments are set \
2328  (as the transformation would then do nothing), or the \
2329  quadrature argument is True but the element order is not \
2330  provided (as the former needs the latter).
2331 
2332  '''
2333  if not isinstance(node, LFRicKern):
2334  raise TransformationError(
2335  f"Error in Dynamo0p3KernelConstTrans transformation. Supplied "
2336  f"node must be a dynamo kernel but found '{type(node)}'.")
2337 
2338  if not options:
2339  options = {}
2340  cellshape = options.get("cellshape", "quadrilateral")
2341  element_order = options.get("element_order", None)
2342  number_of_layers = options.get("number_of_layers", None)
2343  quadrature = options.get("quadrature", False)
2344  if cellshape.lower() != "quadrilateral":
2345  # Only quadrilaterals are currently supported
2346  raise TransformationError(
2347  f"Error in Dynamo0p3KernelConstTrans transformation. Supplied "
2348  f"cellshape must be set to 'quadrilateral' but found "
2349  f"'{cellshape}'.")
2350 
2351  if element_order is not None and \
2352  (not isinstance(element_order, int) or element_order < 0):
2353  # element order must be 0 or a positive integer
2354  raise TransformationError(
2355  f"Error in Dynamo0p3KernelConstTrans transformation. The "
2356  f"element_order argument must be >= 0 but found "
2357  f"'{element_order}'.")
2358 
2359  if number_of_layers is not None and \
2360  (not isinstance(number_of_layers, int) or number_of_layers < 1):
2361  # number of layers must be a positive integer
2362  raise TransformationError(
2363  f"Error in Dynamo0p3KernelConstTrans transformation. The "
2364  f"number_of_layers argument must be > 0 but found "
2365  f"'{number_of_layers}'.")
2366 
2367  if quadrature not in [False, True]:
2368  # quadrature must be a boolean value
2369  raise TransformationError(
2370  f"Error in Dynamo0p3KernelConstTrans transformation. The "
2371  f"quadrature argument must be boolean but found "
2372  f"'{quadrature}'.")
2373 
2374  if element_order is None and not number_of_layers:
2375  # As a minimum, element order or number of layers must have values.
2376  raise TransformationError(
2377  "Error in Dynamo0p3KernelConstTrans transformation. At least "
2378  "one of element_order or number_of_layers must be set "
2379  "otherwise this transformation does nothing.")
2380 
2381  if quadrature and element_order is None:
2382  # if quadrature then element order
2383  raise TransformationError(
2384  "Error in Dynamo0p3KernelConstTrans transformation. If "
2385  "quadrature is set then element_order must also be set (as "
2386  "the values of the former are derived from the latter.")
2387 
2388 
Here is the caller graph for this function:

Member Data Documentation

◆ space_to_dofs

dictionary psyclone.transformations.Dynamo0p3KernelConstTrans.space_to_dofs
static
Initial value:
= {"w3": (lambda n: (n+1)**3),
"w2": (lambda n: 3*(n+2)*(n+1)**2),
"w1": (lambda n: 3*(n+2)**2*(n+1)),
"w0": (lambda n: (n+2)**3),
"wtheta": (lambda n: (n+2)*(n+1)**2),
"w2h": (lambda n: 2*(n+2)*(n+1)**2),
"w2v": (lambda n: (n+2)*(n+1)**2),
"w2broken": (lambda n: 3*(n+1)**2*(n+2)),
"wchi": (lambda n: (n+1)**3),
"w2trace": (lambda n: 6*(n+1)**2),
"w2htrace": (lambda n: 4*(n+1)**2),
"w2vtrace": (lambda n: 2*(n+1)**2)}

Definition at line 2112 of file transformations.py.


The documentation for this class was generated from the following file: