Reference Guide  2.5.0
nemo.py
1 # -----------------------------------------------------------------------------
2 # BSD 3-Clause License
3 #
4 # Copyright (c) 2017-2024, Science and Technology Facilities Council.
5 # All rights reserved.
6 #
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions are met:
9 #
10 # * Redistributions of source code must retain the above copyright notice, this
11 # list of conditions and the following disclaimer.
12 #
13 # * Redistributions in binary form must reproduce the above copyright notice,
14 # this list of conditions and the following disclaimer in the documentation
15 # and/or other materials provided with the distribution.
16 #
17 # * Neither the name of the copyright holder nor the names of its
18 # contributors may be used to endorse or promote products derived from
19 # this software without specific prior written permission.
20 #
21 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 # POSSIBILITY OF SUCH DAMAGE.
33 # ----------------------------------------------------------------------------
34 # Authors: R. W. Ford, A. R. Porter, S. Siso and N. Nobre, STFC Daresbury Lab
35 # Modified work Copyright (c) 2019 by J. Henrichs, Bureau of Meteorology
36 
37 '''This module implements the PSyclone NEMO API by specialising
38  the required base classes for code generation (PSy, Invokes,
39  Invoke, InvokeSchedule, Loop, CodedKern, Arguments and KernelArgument).
40 
41 '''
42 
43 from fparser.two.utils import walk
44 from fparser.two import Fortran2003
45 from psyclone.configuration import Config
46 from psyclone.errors import InternalError
47 from psyclone.psyGen import PSy, Invokes, Invoke, InvokeSchedule, InlinedKern
48 from psyclone.psyir.backend.fortran import FortranWriter
49 from psyclone.psyir.nodes import Routine
50 from psyclone.psyir.frontend.fparser2 import Fparser2Reader
51 
52 
54  '''
55  Represents a NEMO 'Invoke' which, since NEMO is existing code, means
56  an existing program unit, e.g. a subroutine.
57 
58  :param sched: PSyIR node representing the program unit.
59  :type sched: :py:class:`psyclone.psyir.nodes.Routine`
60  :param str name: the name of this Invoke (program unit).
61  :param invokes: the Invokes object that holds this Invoke.
62  :type invokes: :py:class:`psyclone.nemo.NemoInvokes`
63 
64  '''
65  def __init__(self, sched, name, invokes):
66  # pylint: disable=super-init-not-called
67  self._invokes_invokes_invokes = invokes
68  self._schedule_schedule_schedule = sched
69  self._name_name_name = name
70  self._schedule_schedule_schedule.invoke = self
71 
72 
74  '''
75  Class capturing information on all 'Invokes' (program units) within
76  a single NEMO source file.
77 
78  :param psyir: the language-level PSyIR for the whole Fortran source file.
79  :type psyir: :py:class:`psyclone.psyir.nodes.Container`
80  :param psy: the PSy object containing all information for this source file.
81  :type psy: :py:class:`psyclone.nemo.NemoPSy`
82 
83  '''
84  def __init__(self, psyir, psy):
85  # pylint: disable=super-init-not-called
86  self._psy_psy_psy = psy
87  self.invoke_mapinvoke_mapinvoke_map = {}
88  self.invoke_listinvoke_listinvoke_list = []
89 
90  # Transform the language-level PSyIR into NEMO-specific PSyIR
91  # pylint: disable=import-outside-toplevel
92  from psyclone.domain.nemo.transformations import CreateNemoPSyTrans
93  CreateNemoPSyTrans().apply(psyir)
94  routines = psyir.walk(Routine)
95 
96  # Create an Invoke for each routine we've found
97  for subroutine in routines:
98 
99  my_invoke = NemoInvoke(subroutine, subroutine.name, self)
100  self.invoke_mapinvoke_mapinvoke_map[subroutine.name] = my_invoke
101  self.invoke_listinvoke_listinvoke_list.append(my_invoke)
102 
103 
104 class NemoPSy(PSy):
105  '''
106  The NEMO-specific PSy class. This creates a NEMO-specific
107  invokes object (which controls all the required invocation calls).
108 
109  :param ast: the fparser2 AST for this PSy layer (i.e. NEMO routine)
110  :type ast: :py:class:`fparser.two.Fortran2003.Main_Program` or \
111  :py:class:`fparser.two.Fortran2003.Subroutine_Subprogram` or \
112  :py:class:`fparser.two.Fortran2003.Function_Subprogram`.
113  :raises InternalError: if no Fortran2003.Name nodes are found in the \
114  supplied AST.
115  '''
116  def __init__(self, ast):
117  # pylint: disable=super-init-not-called
118  names = walk(ast.content, Fortran2003.Name)
119  # The name of the program unit will be the first in the list
120  if not names:
121  raise InternalError("Found no names in supplied Fortran - should "
122  "be impossible!")
123  self._name_name_name = str(names[0]) + "_psy"
124 
125  processor = Fparser2Reader()
126  psyir = processor.generate_psyir(ast)
127 
128  self._invokes_invokes_invokes = NemoInvokes(psyir, self)
129  self._container_container_container = psyir
130 
131  @property
132  def gen(self):
133  '''
134  Generate the Fortran for the NEMO code represented by this
135  NemoPSy object.
136 
137  :returns: the Fortran code.
138  :rtype: str
139 
140  '''
141  enable_checks = Config.get().backend_checks_enabled
142  fwriter = FortranWriter(check_global_constraints=enable_checks)
143  return fwriter(self._container_container_container)
144 
145 
147  '''
148  The NEMO-specific InvokeSchedule sub-class. This is the top-level node in
149  PSyclone's IR of a NEMO program unit (program, subroutine etc).
150 
151  :param str name: the name of this NemoInvokeSchedule (Routine).
152  :param invoke: the Invoke to which this NemoInvokeSchedule belongs.
153  :type invoke: :py:class:`psyclone.nemo.NemoInvoke`
154  :param kwargs: additional keyword arguments provided to the super class.
155  :type kwargs: unwrapped dict.
156 
157  '''
158  _text_name = "NemoInvokeSchedule"
159 
160  def __init__(self, name, invoke=None, **kwargs):
161  super().__init__(name, None, None, **kwargs)
162 
163  self._invoke_invoke_invoke = invoke
164 
165  def coded_kernels(self):
166  '''
167  Returns a list of all of the user-supplied kernels (as opposed to
168  builtins) that are beneath this node in the PSyIR. In the NEMO API
169  this means all instances of InlinedKern.
170 
171  :returns: all user-supplied kernel calls below this node.
172  :rtype: list of :py:class:`psyclone.psyGen.CodedKern`
173  '''
174  return self.walk(InlinedKern)
def gen(self)
Definition: nemo.py:132