Reference Guide  2.5.0
psyclone.domain.gocean.transformations.gocean_move_iteration_boundaries_inside_kernel_trans.GOMoveIterationBoundariesInsideKernelTrans Class Reference
Inheritance diagram for psyclone.domain.gocean.transformations.gocean_move_iteration_boundaries_inside_kernel_trans.GOMoveIterationBoundariesInsideKernelTrans:
Collaboration diagram for psyclone.domain.gocean.transformations.gocean_move_iteration_boundaries_inside_kernel_trans.GOMoveIterationBoundariesInsideKernelTrans:

Public Member Functions

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

Detailed Description

 Provides a transformation that moves iteration boundaries that are
encoded in the Loops lower_bound() and upper_bound() methods to a mask
inside the kernel with the boundaries passed as kernel arguments.

For example the following kernel call:

.. code-block:: fortran

    do i = 2, N - 1
        do j = 2, N - 1
            kernel(i, j, field)
        end do
    end do

will be transformed to:

.. code-block:: fortran

    startx = 2
    stopx = N - 1
    starty = 2
    stopy = N - 1
    do i = 1, size(field, 1)
        do j = 1, size(field, 2)
            kernel(i, j, field, startx, stopx, starty, stopy)
        end do
    end do

additionally a mask like the following one will be introduced in the
kernel code:

.. code-block:: fortran

    if (i < startx .or. i > stopx .or. j < starty .or. j > stopy) then
        return
    end if

Definition at line 47 of file gocean_move_iteration_boundaries_inside_kernel_trans.py.

Member Function Documentation

◆ apply()

def psyclone.domain.gocean.transformations.gocean_move_iteration_boundaries_inside_kernel_trans.GOMoveIterationBoundariesInsideKernelTrans.apply (   self,
  node,
  options = None 
)
Apply this transformation to the supplied node.

:param node: the node to transform.
:type node: :py:class:`psyclone.gocean1p0.GOKern`
:param options: a dictionary with options for transformations.
:type options: Optional[Dict[str, Any]]

Reimplemented from psyclone.psyGen.Transformation.

Definition at line 112 of file gocean_move_iteration_boundaries_inside_kernel_trans.py.

112  def apply(self, node, options=None):
113  '''Apply this transformation to the supplied node.
114 
115  :param node: the node to transform.
116  :type node: :py:class:`psyclone.gocean1p0.GOKern`
117  :param options: a dictionary with options for transformations.
118  :type options: Optional[Dict[str, Any]]
119 
120  '''
121  self.validate(node, options)
122 
123  # Get useful references
124  invoke_st = node.ancestor(InvokeSchedule).symbol_table
125  inner_loop = node.ancestor(Loop)
126  outer_loop = inner_loop.ancestor(Loop)
127  cursor = outer_loop.position
128 
129  # Make sure the boundary symbols in the PSylayer exist
130  inv_xstart = invoke_st.find_or_create_tag(
131  "xstart_" + node.name, root_name="xstart", symbol_type=DataSymbol,
132  datatype=INTEGER_TYPE)
133  inv_xstop = invoke_st.find_or_create_tag(
134  "xstop_" + node.name, root_name="xstop", symbol_type=DataSymbol,
135  datatype=INTEGER_TYPE)
136  inv_ystart = invoke_st.find_or_create_tag(
137  "ystart_" + node.name, root_name="ystart", symbol_type=DataSymbol,
138  datatype=INTEGER_TYPE)
139  inv_ystop = invoke_st.find_or_create_tag(
140  "ystop_" + node.name, root_name="ystop", symbol_type=DataSymbol,
141  datatype=INTEGER_TYPE)
142 
143  # If the kernel acts on the whole iteration space, the boundary values
144  # are not needed. This also avoids adding duplicated arguments if this
145  # transformation is applied more than once to the same kernel. But the
146  # declaration and initialisation above still needs to exist because the
147  # boundary variables are expected to exist by the generation code.
148  if (inner_loop.field_space == "go_every" and
149  outer_loop.field_space == "go_every" and
150  inner_loop.iteration_space == "go_all_pts" and
151  outer_loop.iteration_space == "go_all_pts"):
152  return node.root, None
153 
154  # Initialise the boundary values provided by the Loop construct
155  assign1 = Assignment.create(Reference(inv_xstart),
156  inner_loop.start_expr.copy())
157  outer_loop.parent.children.insert(cursor, assign1)
158  cursor = cursor + 1
159  assign2 = Assignment.create(Reference(inv_xstop),
160  inner_loop.stop_expr.copy())
161  outer_loop.parent.children.insert(cursor, assign2)
162  cursor = cursor + 1
163  assign3 = Assignment.create(Reference(inv_ystart),
164  outer_loop.start_expr.copy())
165  outer_loop.parent.children.insert(cursor, assign3)
166  cursor = cursor + 1
167  assign4 = Assignment.create(Reference(inv_ystop),
168  outer_loop.stop_expr.copy())
169  outer_loop.parent.children.insert(cursor, assign4)
170 
171  # Update Kernel Call argument list
172  for symbol in [inv_xstart, inv_xstop, inv_ystart, inv_ystop]:
173  node.arguments.append(symbol.name, "go_i_scalar")
174 
175  # Now that the boundaries are inside the kernel, the looping should go
176  # through all the field points
177  inner_loop.field_space = "go_every"
178  outer_loop.field_space = "go_every"
179  inner_loop.iteration_space = "go_all_pts"
180  outer_loop.iteration_space = "go_all_pts"
181 
182  # Update Kernel
183  kschedule = node.get_kernel_schedule()
184  kernel_st = kschedule.symbol_table
185  iteration_indices = kernel_st.iteration_indices
186  data_arguments = kernel_st.data_arguments
187 
188  # Create new symbols and insert them as kernel arguments at the end of
189  # the kernel argument list
190  xstart_symbol = kernel_st.new_symbol(
191  "xstart", symbol_type=DataSymbol, datatype=INTEGER_TYPE,
192  interface=ArgumentInterface(ArgumentInterface.Access.READ))
193  xstop_symbol = kernel_st.new_symbol(
194  "xstop", symbol_type=DataSymbol, datatype=INTEGER_TYPE,
195  interface=ArgumentInterface(ArgumentInterface.Access.READ))
196  ystart_symbol = kernel_st.new_symbol(
197  "ystart", symbol_type=DataSymbol, datatype=INTEGER_TYPE,
198  interface=ArgumentInterface(ArgumentInterface.Access.READ))
199  ystop_symbol = kernel_st.new_symbol(
200  "ystop", symbol_type=DataSymbol, datatype=INTEGER_TYPE,
201  interface=ArgumentInterface(ArgumentInterface.Access.READ))
202  kernel_st.specify_argument_list(
203  iteration_indices + data_arguments +
204  [xstart_symbol, xstop_symbol, ystart_symbol, ystop_symbol])
205 
206  # Create boundary masking conditions
207  condition1 = BinaryOperation.create(
208  BinaryOperation.Operator.LT,
209  Reference(iteration_indices[0]),
210  Reference(xstart_symbol))
211  condition2 = BinaryOperation.create(
212  BinaryOperation.Operator.GT,
213  Reference(iteration_indices[0]),
214  Reference(xstop_symbol))
215  condition3 = BinaryOperation.create(
216  BinaryOperation.Operator.LT,
217  Reference(iteration_indices[1]),
218  Reference(ystart_symbol))
219  condition4 = BinaryOperation.create(
220  BinaryOperation.Operator.GT,
221  Reference(iteration_indices[1]),
222  Reference(ystop_symbol))
223 
224  condition = BinaryOperation.create(
225  BinaryOperation.Operator.OR,
226  BinaryOperation.create(
227  BinaryOperation.Operator.OR,
228  condition1,
229  condition2),
230  BinaryOperation.create(
231  BinaryOperation.Operator.OR,
232  condition3,
233  condition4)
234  )
235 
236  # Insert the conditional mask as the first statement of the kernel
237  if_statement = IfBlock.create(condition, [Return()])
238  kschedule.children.insert(0, if_statement)
239 
240 
241 # For Sphinx AutoAPI documentation generation

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.domain.gocean.transformations.gocean_move_iteration_boundaries_inside_kernel_trans.GOMoveIterationBoundariesInsideKernelTrans.name (   self)
Returns the name of this transformation as a string.

Reimplemented from psyclone.psyGen.Transformation.

Definition at line 90 of file gocean_move_iteration_boundaries_inside_kernel_trans.py.

90  def name(self):
91  '''Returns the name of this transformation as a string.'''
92  return "GOMoveIterationBoundariesInsideKernelTrans"
93 
Here is the caller graph for this function:

◆ validate()

def psyclone.domain.gocean.transformations.gocean_move_iteration_boundaries_inside_kernel_trans.GOMoveIterationBoundariesInsideKernelTrans.validate (   self,
  node,
  options = None 
)
Ensure that it is valid to apply this transformation to the
supplied node.

:param node: the node to validate.
:type node: :py:class:`psyclone.gocean1p0.GOKern`
:param options: a dictionary with options for transformations.
:type options: Optional[Dict[str, Any]]

:raises TransformationError: if the node is not a GOKern.

Reimplemented from psyclone.psyGen.Transformation.

Definition at line 94 of file gocean_move_iteration_boundaries_inside_kernel_trans.py.

94  def validate(self, node, options=None):
95  '''Ensure that it is valid to apply this transformation to the
96  supplied node.
97 
98  :param node: the node to validate.
99  :type node: :py:class:`psyclone.gocean1p0.GOKern`
100  :param options: a dictionary with options for transformations.
101  :type options: Optional[Dict[str, Any]]
102 
103  :raises TransformationError: if the node is not a GOKern.
104 
105  '''
106  if not isinstance(node, GOKern):
107  raise TransformationError(
108  f"Error in {self.name} transformation. This transformation "
109  f"can only be applied to 'GOKern' nodes, but found "
110  f"'{type(node).__name__}'.")
111 
Here is the caller graph for this function:

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