Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/psyclone/domain/lfric/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@
from psyclone.domain.lfric.lfric_cell_iterators import LFRicCellIterators
from psyclone.domain.lfric.lfric_driver_creator import \
LFRicDriverCreator
from psyclone.domain.lfric.lfric_symbol_table import LFRicSymbolTable
from psyclone.domain.lfric.lfric_types import LFRicTypes
from psyclone.domain.lfric.kern_stub_arg_list import KernStubArgList
from psyclone.domain.lfric.lfric_invoke import LFRicInvoke
Expand Down
36 changes: 14 additions & 22 deletions src/psyclone/domain/lfric/algorithm/lfric_alg.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
'''

from psyclone.domain.lfric import (KernCallInvokeArgList, LFRicConstants,
LFRicSymbolTable, LFRicTypes)
LFRicTypes)
from psyclone.domain.lfric.algorithm.psyir import (
LFRicAlgorithmInvokeCall, LFRicBuiltinFunctorFactory, LFRicKernelFunctor)
from psyclone.domain.lfric import LFRicKern
Expand All @@ -52,7 +52,7 @@
from psyclone.parse.utils import ParseError
from psyclone.psyir.frontend.fortran import FortranReader
from psyclone.psyir.nodes import (Assignment, Container, Literal,
Reference, Routine, ScopingNode)
Reference, Routine)
from psyclone.psyir.symbols import (
UnresolvedType, UnsupportedFortranType, DataTypeSymbol, DataSymbol,
ArrayType, ImportInterface, ContainerSymbol, RoutineSymbol,
Expand All @@ -65,21 +65,20 @@ class LFRicAlg:
layer from Kernel metadata.

'''
def create_from_kernel(self, name, kernel_path):
def create_from_kernel(self, name: str, kernel_path: str) -> Container:
'''
Generates LFRic algorithm PSyIR that calls the supplied kernel through
an 'invoke'. All of the arguments required by the kernel are
constructed and initialised appropriately. Fields and scalars are all
set to unity.

:param str name: name to use for the algorithm subroutine.
:param str kernel_path: location of Kernel source code.
:param name: name to use for the algorithm subroutine.
:param kernel_path: location of Kernel source code.

:returns: LFRic algorithm PSyIR.
:rtype: :py:class:`psyclone.psyir.nodes.Container`

:raises NotImplementedError: if the specified kernel file does not \
follow the LFRic naming convention by having a module with a name \
:raises NotImplementedError: if the specified kernel file does not
follow the LFRic naming convention by having a module with a name
ending in '_mod'.

'''
Expand Down Expand Up @@ -130,7 +129,7 @@ def create_from_kernel(self, name, kernel_path):
# arbitrary value, we use an *integer* literal for this, irrespective
# of the actual type of the scalar argument. The compiler/run-time will
# take care of appropriate type casting.
table.add_lfric_precision_symbol("i_def")
LFRicTypes.add_precision_symbol(table, "i_def")
for sym in kern_args.scalars:
sub.addchild(Assignment.create(
Reference(sym),
Expand All @@ -143,7 +142,7 @@ def create_from_kernel(self, name, kernel_path):
# integer rather than real) we rely on type casting by the
# compiler/run-time.
factory = LFRicBuiltinFunctorFactory.get()
table.add_lfric_precision_symbol("r_def")
LFRicTypes.add_precision_symbol(table, "r_def")
kernel_list = []
for sym, _ in kern_args.fields:
kernel_list.append(
Expand All @@ -167,7 +166,7 @@ def create_from_kernel(self, name, kernel_path):
return cont

@staticmethod
def create_alg_routine(name):
def create_alg_routine(name: str) -> Container:
'''
Creates an LFRic algorithm subroutine within a module. The
generated subroutine has three arguments:
Expand All @@ -176,22 +175,17 @@ def create_alg_routine(name):
* chi: coordinate field (optional).
* panel_id: field mapping cells to panel IDs (optional).

:param str name: the name to give the created routine. The associated \
:param str name: the name to give the created routine. The associated
container will have "_mod" appended to this name.

:returns: a container.
:rtype: :py:class:`psyclone.psyir.nodes.Container`

:raises TypeError: if the 'name' argument is of the wrong type.

'''
if not isinstance(name, str):
raise TypeError(f"Supplied routine name must be a str but got "
f"'{type(name).__name__}'")
# Make sure the scoping node creates LFRicSymbolTables
# pylint: disable=protected-access
# TODO #1954 Remove the protected access using a factory
ScopingNode._symbol_table_class = LFRicSymbolTable
alg_sub = Routine.create(name)
table = alg_sub.symbol_table

Expand Down Expand Up @@ -302,24 +296,22 @@ def _create_function_spaces(self, prog, fspaces):
prog.addchild(cblock)

@staticmethod
def initialise_field(prog, sym, space):
def initialise_field(prog: Routine, sym: DataSymbol, space: str) -> None:
'''
Creates the PSyIR for initialisation of the field or field vector
represented by the supplied symbol and adds it to the supplied
routine.

:param prog: the routine to which to add initialisation code.
:type prog: :py:class:`psyclone.psyir.nodes.Routine`
:param sym: the symbol representing the LFRic field.
:type sym: :py:class:`psyclone.psyir.symbols.DataSymbol`
:param str space: the function space of the field.
:param space: the function space of the field.

:raises InternalError: if the supplied symbol is of the wrong type.

'''
reader = FortranReader()

prog.symbol_table.add_lfric_precision_symbol("i_def")
LFRicTypes.add_precision_symbol(prog.symbol_table, "i_def")

if isinstance(sym.datatype, DataTypeSymbol):
# Single field argument.
Expand Down
9 changes: 4 additions & 5 deletions src/psyclone/domain/lfric/arg_ordering.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,11 @@
# The next two imports cannot be merged, since this would create
# a circular dependency.
from psyclone.domain.lfric import LFRicConstants
from psyclone.domain.lfric.lfric_symbol_table import LFRicSymbolTable
from psyclone.domain.lfric.metadata_to_arguments_rules import (
MetadataToArgumentsRules)
from psyclone.errors import GenerationError, InternalError
from psyclone.psyir.nodes import ArrayReference, Reference
from psyclone.psyir.symbols import DataSymbol, ArrayType
from psyclone.psyir.symbols import DataSymbol, ArrayType, SymbolTable


class ArgOrdering:
Expand Down Expand Up @@ -87,7 +86,7 @@ def __init__(self, kern):
self._arg_index_to_metadata_index = {}

@property
def _symtab(self):
def _symtab(self) -> SymbolTable:
''' Provide a reference to the associate Invoke SymbolTable, usually
following the `self._kernel.ancestor(InvokeSchedule)._symbol_table`
path unless a _forced_symtab has been provided.
Expand All @@ -98,15 +97,15 @@ def _symtab(self):
Note: This could be improved by TODO #2503

:returns: the associate invoke symbol table.
:rtype: :py:class:`psyclone.psyir.symbols.SymbolTable`

'''
if self._forced_symtab:
return self._forced_symtab
if self._kern and self._kern.ancestor(psyGen.InvokeSchedule):
# _kern may be outdated, so go back up to the invoke first
current_invoke = self._kern.ancestor(psyGen.InvokeSchedule).invoke
return current_invoke.schedule.symbol_table
return LFRicSymbolTable()
return SymbolTable()

def psyir_append(self, node):
'''Appends a PSyIR node to the PSyIR argument list.
Expand Down
45 changes: 28 additions & 17 deletions src/psyclone/domain/lfric/kern_call_arg_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,9 @@
should be removed as we migrate to use PSyIR in LFRic.
'''

from __future__ import annotations
from dataclasses import dataclass
from typing import Optional, Tuple
from typing import Optional, Tuple, TYPE_CHECKING

from psyclone import psyGen
from psyclone.core import AccessType, Signature, VariablesAccessMap
Expand All @@ -57,6 +58,8 @@
DataSymbol, DataTypeSymbol, UnresolvedType, ContainerSymbol,
ImportInterface, ScalarType, ArrayType, Symbol, UnsupportedFortranType,
ArgumentInterface)
if TYPE_CHECKING:
from psyclone.lfric import LFRicKernelArgument

# psyir has classes created at runtime
# pylint: disable=no-member
Expand Down Expand Up @@ -139,7 +142,7 @@ def get_user_type(self, module_name: str,
mod_sym_tab = self._symtab

# The user-defined type must be declared in the same symbol
# table as the container (otherwise errors will happen later):
# table as the container.
user_type_symbol = mod_sym_tab.find_or_create(
user_type,
symbol_type=DataTypeSymbol,
Expand Down Expand Up @@ -355,14 +358,15 @@ def cma_operator(self, arg,
self.append(sym.name, var_accesses, mode=mode,
metadata_posn=arg.metadata_index)

def field_vector(self, argvect,
var_accesses: Optional[VariablesAccessMap] = None):
def field_vector(self,
argvect: "LFRicKernelArgument",
var_accesses: Optional[VariablesAccessMap] = None
) -> None:
'''Add the field vector associated with the argument 'argvect' to the
argument list. If supplied it also stores these accesses to the
var_access object.

:param argvect: the field vector to add.
:type argvect: :py:class:`psyclone.lfric.LFRicKernelArgument`
:param var_accesses: optional VariablesAccessMap instance to store
the information about variable accesses.

Expand All @@ -380,8 +384,9 @@ def field_vector(self, argvect,
f"{argvect.name}_{idx}:{suffix}")
if self._kern.iterates_over == "dof":
# If dof kernel, add access to the field by dof ref
dof_sym = self._symtab.find_or_create_integer_symbol(
"df", tag="dof_loop_idx")
dof_sym = self._symtab.find_or_create(
"df", tag="dof_loop_idx", symbol_type=DataSymbol,
datatype=LFRicTypes("LFRicIntegerScalarDataType")())
# TODO #1010 removes the need to declare type and
# allows this to be fixed
self.append_array_reference(cmpt_sym.name,
Expand All @@ -400,12 +405,14 @@ def field_vector(self, argvect,
var_accesses.add_access(Signature(argvect.name), argvect.access,
self._kern)

def field(self, arg, var_accesses: Optional[VariablesAccessMap] = None):
def field(self,
arg: "LFRicKernelArgument",
var_accesses: Optional[VariablesAccessMap] = None
) -> None:
'''Add the field array associated with the argument 'arg' to the
argument list. If supplied it also stores this access in var_accesses.

:param arg: the field to be added.
:type arg: :py:class:`psyclone.lfric.LFRicKernelArgument`
:param var_accesses: optional VariablesAccessMap instance to store
the information about variable accesses.

Expand All @@ -418,8 +425,9 @@ def field(self, arg, var_accesses: Optional[VariablesAccessMap] = None):

if self._kern.iterates_over == "dof":
# If dof kernel, add access to the field by dof ref
dof_sym = self._symtab.find_or_create_integer_symbol(
"df", tag="dof_loop_idx")
dof_sym = self._symtab.find_or_create(
"df", tag="dof_loop_idx", symbol_type=DataSymbol,
datatype=LFRicTypes("LFRicIntegerScalarDataType")())
# TODO #1010 removes the need to declare type and
# allows this to be fixed
self.append_array_reference(sym.name, [Reference(dof_sym)],
Expand Down Expand Up @@ -977,15 +985,17 @@ def cell_ref_name(
and similar methods should be refactored.

'''
cell_sym = self._symtab.find_or_create_integer_symbol(
"cell", tag="cell_loop_idx")
cell_sym = self._symtab.find_or_create(
"cell", tag="cell_loop_idx", symbol_type=DataSymbol,
datatype=LFRicTypes("LFRicIntegerScalarDataType")())
if var_accesses is not None:
var_accesses.add_access(Signature(cell_sym.name), AccessType.READ,
self._kern)

if self._kern.is_coloured():
colour_sym = self._symtab.find_or_create_integer_symbol(
"colour", tag="colours_loop_idx")
colour_sym = self._symtab.find_or_create(
"colour", tag="colours_loop_idx", symbol_type=DataSymbol,
datatype=LFRicTypes("LFRicIntegerScalarDataType")())
if var_accesses is not None:
var_accesses.add_access(Signature(colour_sym.name),
AccessType.READ, self._kern)
Expand All @@ -995,8 +1005,9 @@ def cell_ref_name(
loop_type = self._kern.ancestor(LFRicLoop).loop_type

if loop_type == "cells_in_tile":
tile_sym = self._symtab.find_or_create_integer_symbol(
"tile", tag="tile_loop_idx")
tile_sym = self._symtab.find_or_create(
"tile", tag="tile_loop_idx", symbol_type=DataSymbol,
datatype=LFRicTypes("LFRicIntegerScalarDataType")())
map_sym = self._symtab.lookup(self._kern.tilecolourmap)
array_ref = ArrayReference.create(
map_sym, [Reference(colour_sym), Reference(tile_sym),
Expand Down
23 changes: 13 additions & 10 deletions src/psyclone/domain/lfric/kern_call_invoke_arg_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,16 @@
of a Kernel as required by an `invoke` of that kernel.
'''

from psyclone.domain.lfric import ArgOrdering, LFRicConstants
# Avoid circular dependency:
from typing import Optional, TYPE_CHECKING
from psyclone.core import VariablesAccessMap
from psyclone.domain.lfric.arg_ordering import ArgOrdering
from psyclone.domain.lfric.lfric_constants import LFRicConstants
from psyclone.domain.lfric.lfric_types import LFRicTypes
from psyclone.psyir.symbols import (
ArrayType, DataSymbol, DataTypeSymbol, UnresolvedType, SymbolTable,
ContainerSymbol, ImportInterface)
if TYPE_CHECKING:
from psyclone.lfric import LFRicKernelArgument


class KernCallInvokeArgList(ArgOrdering):
Expand Down Expand Up @@ -131,19 +135,18 @@ def generate(self, var_accesses=None):
self._halo_depth = None
super().generate(var_accesses)

def scalar(self, scalar_arg, var_accesses=None):
def scalar(self,
scalar_arg: "LFRicKernelArgument",
var_accesses: Optional[VariablesAccessMap] = None
) -> None:
'''
Add the necessary argument for a scalar quantity as well as an
appropriate Symbol to the SymbolTable.

:param scalar_arg: the scalar kernel argument.
:type scalar_arg: :py:class:`psyclone.lfric.LFRicKernelArgument`
:param var_accesses: optional VariablesAccessMap instance that \
stores information about variable accesses.
:type var_accesses: \
:py:class:`psyclone.core.VariablesAccessMap`
:param var_accesses: optional information about variable accesses.

:raises NotImplementedError: if a scalar of type other than real \
:raises NotImplementedError: if a scalar of type other than real
or integer is found.

'''
Expand All @@ -162,7 +165,7 @@ def scalar(self, scalar_arg, var_accesses=None):

consts = LFRicConstants()
precision_name = consts.SCALAR_PRECISION_MAP[scalar_arg.intrinsic_type]
self._symtab.add_lfric_precision_symbol(precision_name)
LFRicTypes.add_precision_symbol(self._symtab, precision_name)

sym = self._symtab.new_symbol(scalar_arg.name,
symbol_type=DataSymbol,
Expand Down
11 changes: 6 additions & 5 deletions src/psyclone/domain/lfric/kernel_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,17 @@
kernel based on the kernel metadata.

'''
from typing import TYPE_CHECKING
from psyclone.core import AccessType
from psyclone.domain.lfric.arg_ordering import ArgOrdering
from psyclone.domain.lfric.lfric_constants import LFRicConstants
from psyclone.domain.lfric.lfric_symbol_table import LFRicSymbolTable
from psyclone.domain.lfric.lfric_types import LFRicTypes
from psyclone.errors import InternalError
from psyclone.psyir.frontend.fparser2 import INTENT_MAPPING
from psyclone.psyir.nodes import Reference
from psyclone.psyir.symbols import ArgumentInterface
from psyclone.psyir.symbols import ArgumentInterface, SymbolTable
if TYPE_CHECKING:
from psyclone.domain.lfric.lfric_kern import LFRicKern


# pylint: disable=too-many-public-methods, no-member
Expand All @@ -72,7 +74,6 @@ class KernelInterface(ArgOrdering):
code when all of its methods are implemented.

:param kern: the kernel for which to create arguments.
:type kern: :py:class:`psyclone.domain.lfric.LFRicKern`

'''
#: Mapping from a generic PSyIR datatype to the equivalent
Expand Down Expand Up @@ -101,14 +102,14 @@ class KernelInterface(ArgOrdering):
"gh_quadrature_edge": "DiffBasisFunctionQrEdgeDataSymbol"}
_read_access = ArgumentInterface(ArgumentInterface.Access.READ)

def __init__(self, kern):
def __init__(self, kern: "LFRicKern"):
super().__init__(kern)
# We need a brand new symbol table, not a reference to the one for
# the Schedule containing this kernel call (which is what the
# ArgOrdering constructor defaults to). This is so that we can
# specify the correct interface for those symbols passed
# as arguments.
self._forced_symtab = LFRicSymbolTable()
self._forced_symtab = SymbolTable()

def generate(self, var_accesses=None):
'''Call the generate base class then add the argument list as it can't
Expand Down
Loading
Loading