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
7 changes: 3 additions & 4 deletions .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,9 @@ jobs:
- run: python -m pip install --upgrade pip
- run: pip install .[doc]
# Now we can check for warnings and broken links
- run: cd doc; make doctest
- run: cd doc; make html SPHINXOPTS="-W --keep-going"
- run: cd doc; make linkcheck
# TODO #2936: There are many doctest issues, so commenting out for now
# - run: cd doc; make doctest
build:
if: ${{ github.repository != 'stfc/PSyclone-mirror' }}
runs-on: ubuntu-latest
Expand Down Expand Up @@ -127,12 +126,12 @@ jobs:
if: ${{ !(matrix.python-version == '3.9') }}
run: |
locale
pytest -n auto --cov=psyclone --cov-report=xml src/psyclone/tests
pytest -n auto --doctest-modules --cov=psyclone --cov-report=xml src/psyclone
- name: Test with pytest and C Locale
if: ${{ matrix.python-version == '3.9' }}
run: |
locale
pytest -n auto --cov=psyclone --cov-report=xml src/psyclone/tests
pytest -n auto --doctest-modules --cov=psyclone --cov-report=xml src/psyclone
env:
LC_ALL: C
LANG: C
Expand Down
6 changes: 3 additions & 3 deletions doc/developer_guide/dependency.rst
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ thread-private. Note that this code does not handle the usage of
# the access information as well as from the symbol table
# into account.
access_sequence = var_accesses[signature]
if symbol.is_array_access(access_info=access_info):
if symbol.is_array_access(access_info=access_sequence):
# It's not a scalar variable, so it will not be private
continue

Expand Down Expand Up @@ -504,7 +504,7 @@ until we find accesses that would prevent parallelisation:
for next_statement in statements:
# Add the variable accesses of the next statement to
# the existing accesses:
next_statement.reference_accesses(accesses)
accesses = next_statement.reference_accesses()
# Stop when the next statement can not be parallelised
# together with the previous accesses:
if not can_be_parallelised(accesses):
Expand Down Expand Up @@ -581,7 +581,7 @@ can be parallelised:
.. testoutput::
:hide:

Error: The write access to 'a(i,i)' and the read access to 'a(i + 1,i + 1)' are dependent and cannot be parallelised. Variable: 'a'.
Error: The write access to 'a(i,i)' in 'a(i,i) = j + k' and the read access to 'a(i + 1,i + 1)' in 'a(i,i) = a(i + 1,i + 1)' are dependent and cannot be parallelised. Variable: 'a'.

.. _defusechain:

Expand Down
28 changes: 0 additions & 28 deletions doc/developer_guide/module_manager.rst
Original file line number Diff line number Diff line change
Expand Up @@ -115,34 +115,6 @@ However, it also provides methods (``get_used_module_names``,
``get_used_symbols_from_modules``) for interrogating the parse tree which
can be useful if it is not possible to represent this in PSyIR.

An example usage of the ``ModuleManager`` and ``ModuleInfo`` objects,
which prints the filenames of all modules used in ``tl_testkern_mod``:

.. testcode ::

mod_manager = ModuleManager.get()
# Add the path to the PSyclone LFRic example codes:
mod_manager.add_search_path("../src/psyclone/tests/test_files/"
"lfric")

testkern_info = mod_manager.get_module_info("tl_testkern_mod")

used_mods = testkern_info.get_used_module_names()
# Sort the modules so we get a reproducible output ordering
used_mods_list = sorted(list(used_mods))
for module_name in used_mods_list:
mod_info = mod_manager.get_module_info(module_name)
print("Module:", module_name, os.path.basename(mod_info.filename))

.. testoutput::

Module: argument_mod argument_mod.f90
Module: constants_mod constants_mod.f90
Module: fs_continuity_mod fs_continuity_mod.f90
Module: kernel_mod kernel_mod.f90



FileInfo
========

Expand Down
2 changes: 1 addition & 1 deletion doc/developer_guide/psyir_symbols.rst
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ specialisations are possible:
>>> # The following statement would fail because the initial_value doesn't
>>> # match the datatype of the symbol:
>>> # sym2.specialise(DataSymbol, datatype=ScalarType.integer_type(),
... initial_value=3.14)
>>> # initial_value=3.14)
>>> # The following statement is valid and initial_value is set to 3
>>> # (and is_constant will default to False):
>>> sym2.specialise(DataSymbol, datatype=ScalarType.integer_type(), initial_value=3)
Expand Down
8 changes: 0 additions & 8 deletions doc/developer_guide/transformations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,6 @@
.. -----------------------------------------------------------------------------
.. Written by R. W. Ford, A. R. Porter, S. Siso and N. Nobre, STFC Daresbury Lab

.. testsetup::

# Define GOCEAN_SOURCE_FILE to point to an existing gocean 1.0 file.
GOCEAN_SOURCE_FILE = ("../src/psyclone/tests/test_files/"
"gocean1p0/test11_different_iterates_over_one_invoke.f90")
# Define NEMO_SOURCE_FILE to point to an existing nemo file.
NEMO_SOURCE_FILE = ("../examples/nemo/code/tra_adv.F90")


Transformations
###############
Expand Down
4 changes: 2 additions & 2 deletions doc/user_guide/psyir.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
.. testsetup::

from psyclone.psyir.symbols import DataSymbol, ScalarType, ArrayType
from psyclone.psyir.nodes import Reference
from psyclone.psyir.nodes import Reference

.. _psyir-ug:

Expand Down Expand Up @@ -268,7 +268,7 @@ example:
... ScalarType.Precision.SINGLE)
>>> bool_type = ScalarType(ScalarType.Intrinsic.BOOLEAN, 4)
>>> symbol = DataSymbol("rdef", int_type, initial_value=4)
>>> scalar_type = ScalarType(ScalarType.Intrinsic.REAL, symbol)
>>> scalar_type = ScalarType(ScalarType.Intrinsic.REAL, Reference(symbol))

For convenience ScalarType has static methods to create a number of
common scalar datatypes:
Expand Down
22 changes: 6 additions & 16 deletions src/psyclone/alg_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,26 +72,16 @@ class Alg:
latter allows consistent names to be generated between the
algorithm (calling) and psy (callee) layers.

For example:

>>> from psyclone.algorithm.parse import parse
>>> parse_tree, info = parse("argspec.F90")
>>> from psyclone.psyGen import PSy
>>> psy = PSy(info)
>>> from psyclone.alg_gen import Alg
>>> alg = Alg(parse_tree, psy)
>>> print(alg.gen)

:param parse_tree: an object containing a parse tree of the \
algorithm specification which was produced by the function \
:func:`psyclone.parse.algorithm.parse`. Assumes the algorithm \
will be parsed by fparser2 and expects a valid program unit, \
:param parse_tree: an object containing a parse tree of the
algorithm specification which was produced by the function
:func:`psyclone.parse.algorithm.parse`. Assumes the algorithm
will be parsed by fparser2 and expects a valid program unit,
program, module, subroutine or function.
:type parse_tree: :py:class:`fparser.two.utils.Base`
:param psy: an object containing information about the PSy layer.
:type psy: :py:class:`psyclone.psyGen.PSy`
:param str invoke_name: the name that the algorithm layer uses to \
indicate an invoke call. This is an optional argument that \
:param str invoke_name: the name that the algorithm layer uses to
indicate an invoke call. This is an optional argument that
defaults to the name "invoke".

'''
Expand Down
5 changes: 4 additions & 1 deletion src/psyclone/core/symbolic_maths.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,13 @@ class SymbolicMaths:
provides convenience functions for PSyclone. It has a Singleton
access, e.g.:

>>> from psyclone.psyir.frontend.fortran import FortranReader
>>> from psyclone.psyir.backend.fortran import FortranWriter
>>> from psyclone.core import SymbolicMaths
>>> sympy = SymbolicMaths.get()
>>> # Assume lhs is the PSyIR of 'i+j', and rhs is 'j+i'
>>> reader = FortranReader()
>>> lhs = reader.psyir_from_expression('i+j')
>>> rhs = reader.psyir_from_expression('j+i')
>>> if sympy.equal(lhs, rhs):
... writer = FortranWriter()
... print(f"'{writer(lhs)}' and '{writer(rhs)}' are equal.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,22 +70,15 @@ class GOConstLoopBoundsTrans(Transformation):
In practice, the application of the constant loop bounds transformation
looks something like, e.g.:

>>> from psyclone.parse.algorithm import parse
>>> from psyclone.psyGen import PSyFactory
>>> import os
>>> TEST_API = "gocean"
>>> _, info = parse(os.path.join("tests", "test_files", "gocean1p0",
... "single_invoke.f90"),
... api=TEST_API)
>>> psy = PSyFactory(TEST_API).create(info)
>>> invoke = psy.invokes.get('invoke_0_compute_cu')
>>> schedule = invoke.schedule
>>> from psyclone.tests.utilities import get_psylayer_schedule
>>> filename = "single_invoke.f90"
>>> schedule = get_psylayer_schedule(filename, api="gocean")
>>>
>>> from psyclone.transformations import GOConstLoopBoundsTrans
>>> from psyclone.domain.gocean.transformations import \
GOConstLoopBoundsTrans
>>> clbtrans = GOConstLoopBoundsTrans()
>>>
>>> clbtrans.apply(schedule)
>>> print(schedule.view())

'''

Expand Down
15 changes: 5 additions & 10 deletions src/psyclone/domain/gocean/transformations/gocean_extract_trans.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,24 +46,19 @@


class GOceanExtractTrans(ExtractTrans):
''' GOcean1.0 API application of ExtractTrans transformation \
''' GOcean1.0 API application of ExtractTrans transformation
to extract code into a stand-alone program. For example:

>>> from psyclone.parse.algorithm import parse
>>> from psyclone.psyGen import PSyFactory
>>>
>>> API = "gocean"
>>> FILENAME = "shallow_alg.f90"
>>> ast, invokeInfo = parse(FILENAME, api=API)
>>> psy = PSyFactory(API, distributed_memory=False).create(invoke_info)
>>> schedule = psy.invokes.get('invoke_0').schedule
>>> from psyclone.tests.utilities import get_psylayer_schedule
>>> filename = "shallow/shallow_alg.f90"
>>> schedule = get_psylayer_schedule(filename, api="gocean")
>>>
>>> from psyclone.domain.gocean.transformations import GOceanExtractTrans
>>> etrans = GOceanExtractTrans()
>>>
>>> # Apply GOceanExtractTrans transformation to selected Nodes
>>> etrans.apply(schedule.children[0])
>>> print(schedule.view())

'''

# ------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,15 @@ class GOceanLoopFuseTrans(LoopFuseTrans):
in order to fuse two GOcean loops after performing validity checks (e.g.
that the loops are over the same grid-point type). For example:

>>> from psyclone.parse.algorithm import parse
>>> from psyclone.psyGen import PSyFactory
>>> ast, invokeInfo = parse("shallow_alg.f90")
>>> psy = PSyFactory("gocean").create(invokeInfo)
>>> schedule = psy.invokes.get('invoke_0').schedule
>>> print(schedule.view())
>>> from psyclone.tests.utilities import get_psylayer_schedule
>>> filename = "shallow/shallow_alg.f90"
>>> schedule = get_psylayer_schedule(filename, api="gocean")
>>>
>>> from psyclone.transformations import GOceanLoopFuseTrans
>>> from psyclone.domain.gocean.transformations import GOceanLoopFuseTrans
>>> ftrans = GOceanLoopFuseTrans()
>>> ftrans.apply(schedule[0], schedule[1])
>>> print(schedule.view())

# FIXME
# >>> ftrans.apply(schedule[0], schedule[1])

'''
def __str__(self):
Expand Down
20 changes: 11 additions & 9 deletions src/psyclone/domain/gocean/transformations/gocean_opencl_trans.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,18 @@ class GOOpenCLTrans(Transformation):
InvokeSchedule. Additionally, it will generate OpenCL kernels for
each of the kernels referenced by the Invoke. For example:

>>> from psyclone.parse.algorithm import parse
>>> from psyclone.psyGen import PSyFactory
>>> API = "gocean"
>>> FILENAME = "shallow_alg.f90" # examples/gocean/eg1
>>> ast, invoke_info = parse(FILENAME, api=API)
>>> psy = PSyFactory(API, distributed_memory=False).create(invoke_info)
>>> schedule = psy.invokes.get('invoke_0').schedule
>>> from psyclone.tests.utilities import get_psylayer_schedule
>>> filename = "shallow/shallow_alg.f90"
>>> schedule = get_psylayer_schedule(filename, api="gocean")
>>>
>>> from psyclone.domain.gocean.transformations import (
... GOMoveIterationBoundariesInsideKernelTrans,
... GOOpenCLTrans)
>>> move_trans = GOMoveIterationBoundariesInsideKernelTrans()
>>> ocl_trans = GOOpenCLTrans()
>>> ocl_trans.apply(schedule)
>>> print(schedule.view())

# FIXME: Needs GOMoveIterationBoundariesInsideKernelTrans
# >>> ocl_trans.apply(schedule)

'''
# Specify which OpenCL command queue to use for management operations like
Expand Down
16 changes: 0 additions & 16 deletions src/psyclone/domain/lfric/transformations/lfric_extract_trans.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,22 +49,6 @@ class LFRicExtractTrans(ExtractTrans):
''' LFRic API application of ExtractTrans transformation
to extract code into a stand-alone program. For example:

>>> from psyclone.parse.algorithm import parse
>>> from psyclone.psyGen import PSyFactory
>>>
>>> API = "lfric"
>>> FILENAME = "solver_alg.x90"
>>> ast, invokeInfo = parse(FILENAME, api=API)
>>> psy = PSyFactory(API, distributed_memory=False).create(invoke_info)
>>> schedule = psy.invokes.get('invoke_0').schedule
>>>
>>> from psyclone.domain.lfric.transformations import LFRicExtractTrans
>>> etrans = LFRicExtractTrans()
>>>
>>> # Apply LFRicExtractTrans transformation to selected Nodes
>>> etrans.apply(schedule.children[0:3])
>>> print(schedule.view())

'''

def __init__(self):
Expand Down
25 changes: 14 additions & 11 deletions src/psyclone/domain/lfric/transformations/lfric_loop_fuse_trans.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,20 +56,23 @@ class LFRicLoopFuseTrans(LoopFuseTrans):
>>> from psyclone.psyGen import PSyFactory
>>>
>>> API = "lfric"
>>> FILENAME = "alg.x90"
>>> ast, invokeInfo = parse(FILENAME, api=API)
>>> psy = PSyFactory(API, distributed_memory=False).create(invoke_info)
>>> schedule = psy.invokes.get('invoke_0').schedule
>>>
>>> from psyclone.domain.lfric.transformations import LFRicLoopFuseTrans
>>> ftrans = LFRicLoopFuseTrans()
>>>
>>> ftrans.apply(schedule[0], schedule[1])
>>> print(schedule.view())

# FIXME: Which alg.f90?
# >>> FILENAME = "alg.x90"
# >>> ast, invokeInfo = parse(FILENAME, api=API)
# >>> psy = PSyFactory(API, distributed_memory=False).create(invoke_info)
# >>> schedule = psy.invokes.get('invoke_0').schedule
# >>>
# >>> from psyclone.domain.lfric.transformations import LFRicLoopFuseTrans
# >>> ftrans = LFRicLoopFuseTrans()
# >>>
# >>> ftrans.apply(schedule[0], schedule[1])

# FIXME: doctest compare output code

The optional argument `same_space` can be set as

>>> ftrans.apply(schedule[0], schedule[1], {"same_space": True})
# >>> ftrans.apply(schedule[0], schedule[1], {"same_space": True})

when applying the transformation.

Expand Down
9 changes: 0 additions & 9 deletions src/psyclone/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,15 +239,6 @@ def generate(filename: str,
:raises IOError: if the filename or search path do not exist.
:raises NoInvokesError: if no invokes are found in the algorithm file.

For example:

>>> from psyclone.generator import generate
>>> alg, psy = generate("algspec.f90")
>>> alg, psy = generate("algspec.f90", kernel_paths=["src/kernels"])
>>> alg, psy = generate("algspec.f90", script_name="optimise.py")
>>> alg, psy = generate("algspec.f90", line_length=True)
>>> alg, psy = generate("algspec.f90", distributed_memory=False)

'''
logger = logging.getLogger(__name__)

Expand Down
8 changes: 6 additions & 2 deletions src/psyclone/gocean1p0.py
Original file line number Diff line number Diff line change
Expand Up @@ -566,12 +566,16 @@ def add_bounds(bound_info):
the loop boundaries for the outer and inner loop. The format is a
":" separated tuple:

>>> bound_info = offset-type:field-type:iteration-space:outer-start:
.. code-block::

bound_info = offset-type:field-type:iteration-space:outer-start:
outer-stop:inner-start:inner-stop

Example:

>>> bound_info = go_offset_ne:go_ct:go_all_pts:
.. code-block::

bound_info = go_offset_ne:go_ct:go_all_pts:
{start}-1:{stop}+1:{start}:{stop}

The expressions {start} and {stop} will be replaced with the loop
Expand Down
Loading
Loading