psyclone.domain.lfric.lfric_loop#

This module implements the PSyclone LFRic API by specialising the PSyLoop base class from psyGen.py.

Classes#

  • LFRicLoop: The LFRic-specific PSyLoop class. This passes the LFRic-specific

class psyclone.domain.lfric.lfric_loop.LFRicLoop(loop_type='', **kwargs)[source]#

The LFRic-specific PSyLoop class. This passes the LFRic-specific loop information to the base class so it creates the one we require. Creates LFRic-specific loop bounds when the code is being generated.

Parameters:
  • loop_type (str) – the type (iteration space) of this loop.

  • kwargs (unwrapped dict.) – additional keyword arguments provided to the PSyIR node.

Raises:
  • InternalError – if an unrecognised loop_type is specified.

  • InternalError – if a parent that is descendant from an InvokeSchedule is not provided.

Inheritance

Inheritance diagram of LFRicLoop
create_halo_exchanges()[source]#

Add halo exchanges before this loop as required by fields within this loop. To keep the logic simple we assume that any field that accesses the halo will require a halo exchange and then remove the halo exchange if this is not the case (when previous writers perform sufficient redundant computation). It is implemented this way as the halo exchange class determines whether it is required or not so a halo exchange needs to exist in order to find out. The appropriate logic is coded in the _add_halo_exchange helper method. In some cases a new halo exchange will replace an existing one. In this situation that routine also removes the old one.

gen_mark_halos_clean_dirty()[source]#

Generates the necessary code to mark halo regions for all modified fields as clean or dirty following execution of this loop.

independent_iterations(test_all_variables=False, signatures_to_ignore=None, dep_tools=None)[source]#

This function is an LFRic-specific override of the default method in the Loop class. It allows domain-specific rules to be applied when determining whether or not loop iterations are independent.

Parameters:
  • test_all_variables (bool) – if True, it will test if all variable accesses are independent, otherwise it will stop after the first variable access is found that isn’t.

  • signatures_to_ignore (Optional[ List[psyclone.core.Signature]]) – list of signatures for which to skip the access checks.

  • dep_tools (Optional[ psyclone.psyir.tools.DependencyTools]) – an optional instance of DependencyTools so that the caller can access any diagnostic messages detailing why the loop iterations are not independent.

Returns:

True if the loop iterations are independent, False otherwise.

Return type:

bool

load(kern)[source]#

Load the state of this Loop using the supplied Kernel object. This method is provided so that we can individually construct Loop objects for a given kernel call.

Parameters:

kern (psyclone.domain.lfric.LFRicKern) – Kernel object to use to populate state of Loop

Raises:

GenerationError – if the field updated by the kernel has an unexpected function space or if the kernel’s ‘operates-on’ is not consistent with the loop type.

lower_bound_psyir()[source]#
Return type:

Node

Returns:

the PSyIR for this loop lower bound.

Raises:
  • GenerationError – if self._lower_bound_name is not “start” for sequential code.

  • GenerationError – if self._lower_bound_name is unrecognised.

lower_to_language_level()[source]#

In-place replacement of DSL or high-level concepts into generic PSyIR constructs. This function replaces an LFRicLoop with a PSyLoop and inserts the loop boundaries into the new PSyLoop, or removes the loop node in case of a domain kernel. Once TODO #1731 is done (which should fix the loop boundaries, which atm rely on index of the loop in the schedule, i.e. can change when transformations are applied), this function can likely be removed.

Returns:

the lowered version of this node.

Return type:

psyclone.psyir.node.Node

node_str(colour=True)[source]#

Creates a text summary of this loop node. We override this method from the Loop class because, in LFRic, the function space is now an object and we need to call orig_name on it. We also include the upper loop bound as this can now be modified.

Parameters:

colour (bool) – whether or not to include control codes for colour.

Returns:

text summary of this node, optionally with control codes for colour highlighting.

Return type:

str

set_lower_bound(name, index=None)[source]#

Set the lower bounds of this loop

set_upper_bound(name, halo_depth=None)[source]#

Set the upper bound of this loop.

Parameters:
  • name (str) – Loop upper-bound name. Must be a supported name.

  • halo_depth (Optional[psyclone.psyir.nodes.DataNode | int]) – An optional argument indicating the depth of halo that this loop accesses.

Raises:
  • GenerationError – if supplied with an invalid upper-bound name.

  • GenerationError – if supplied with a halo depth < 1.

  • TypeError – if the supplied halo_depth value is neither an int or DataNode.

update_halo_exchanges()[source]#

add and/or remove halo exchanges due to changes in the loops bounds

property upper_bound_halo_depth#

Returns the index of the upper loop bound. This is None if the upper bound name is not in HALO_ACCESS_LOOP_BOUNDS.

Returns:

the depth of the halo for a loops upper bound. If it is None then a depth has not been provided. The depth value is only valid when the upper-bound name is associated with a halo e.g. ‘cell_halo’.

Return type:

int

property upper_bound_name#

Returns the name of the upper loop bound

upper_bound_psyir()[source]#
Return type:

Node

Returns:

the PSyIR for this loop upper bound.