Skip to content

Commit 696b511

Browse files
authored
Merge pull request #3382 from stfc/1570_remove_default_precision_check_in_reductions
(towards #1570) remove the scalar precision check
2 parents f02c0df + 0202b8b commit 696b511

7 files changed

Lines changed: 113 additions & 52 deletions

File tree

changelog

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
72) PR #3382 towards #1570. Removes the unnecessary check on the precision
2+
of a scalar used in a reduction in the LFRic API.
3+
14
71) PR #3381. Update integration tests to LFRic_apps 3.1.1
25

36
70) PR #3358 for #1734, #2975 and #2949. Improve symbol table consistency

src/psyclone/domain/lfric/lfric_constants.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
# POSSIBILITY OF SUCH DAMAGE.
3333
# -----------------------------------------------------------------------------
3434
# Author: J. Henrichs, Bureau of Meteorology
35-
# Modified: I. Kavcic and L, Turner, Met Office
35+
# Modified: I. Kavcic, L, Turner and A. Pirrie, Met Office
3636
# A. R. Porter, STFC Daresbury Laboratory
3737
# R. W. Ford, STFC Daresbury Laboratory
3838

@@ -389,13 +389,13 @@ def __init__(self) -> None:
389389
# Data structure type mandates its proxy name, Fortran intrinsic type
390390
# of its data and the kind (precision) for the intrinsic type.
391391
LFRicConstants.DATA_TYPE_MAP = {
392-
# 'real'-valued scalar reduction of kind 'r_def' (used for global
393-
# reductions of "field_type" data)
394-
"reduction": {"module": "scalar_mod",
395-
"type": "scalar_type",
396-
"proxy_type": None,
397-
"intrinsic": "real",
398-
"kind": "r_def"},
392+
# 'real'-valued scalar reduction of default kind 'None' (used for
393+
# global reductions of "field_type" data)
394+
"scalar": {"module": "scalar_mod",
395+
"type": "scalar_type",
396+
"proxy_type": None,
397+
"intrinsic": "real",
398+
"kind": None},
399399
# 'real'-valued field with data of kind 'r_def'
400400
"field": {"module": "field_mod",
401401
"type": "field_type",
@@ -573,6 +573,10 @@ def precision_for_type(self, data_type):
573573
:raises InternalError: if an unknown data_type is specified.
574574
575575
'''
576+
invalid_types = ["scalar_type"]
577+
if data_type in invalid_types:
578+
raise ValueError(f"Cannot infer the precision of a '{data_type}'.")
579+
576580
for module_info in self.DATA_TYPE_MAP.values():
577581
if module_info["type"] == data_type:
578582
# TODO #2659 - this method should probably just return a name
@@ -581,8 +585,8 @@ def precision_for_type(self, data_type):
581585
from psyclone.domain.lfric.lfric_types import LFRicTypes
582586
return LFRicTypes(module_info["kind"].upper())
583587

584-
valid = [module_info["type"]
585-
for module_info in self.DATA_TYPE_MAP.values()]
588+
valid = [module_info["type"] for module_info in
589+
self.DATA_TYPE_MAP.values()]
586590
raise InternalError(f"Unknown data type '{data_type}', expected one "
587591
f"of {valid}.")
588592

src/psyclone/lfric.py

Lines changed: 15 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5905,38 +5905,22 @@ def _init_scalar_properties(
59055905
"Reductions for datatypes other than real are not yet "
59065906
"supported in PSyclone.")
59075907

5908-
expected_precision = const.DATA_TYPE_MAP["reduction"]["kind"]
5909-
# If the algorithm information is not being ignored
5910-
# then check that the expected precision and the
5911-
# precision defined in the algorithm layer are
5912-
# the same.
5913-
if check and alg_precision and \
5914-
alg_precision != expected_precision:
5915-
raise GenerationError(
5916-
f"This scalar is a reduction which assumes precision "
5917-
f"of type '{expected_precision}' but the algorithm "
5918-
f"declares this scalar with precision "
5919-
f"'{alg_precision}'.")
5920-
5921-
# Use the default 'real' scalar reduction properties.
5922-
self._precision = expected_precision
5923-
self._data_type = const.DATA_TYPE_MAP["reduction"]["type"]
5924-
self._proxy_data_type = const.DATA_TYPE_MAP[
5925-
"reduction"]["proxy_type"]
5926-
self._module_name = const.DATA_TYPE_MAP["reduction"]["module"]
5908+
self._data_type = const.DATA_TYPE_MAP["scalar"]["type"]
5909+
self._proxy_data_type = None
5910+
self._module_name = const.DATA_TYPE_MAP["scalar"]["module"]
5911+
5912+
# The precision of the symbol does not depend on whether
5913+
# it is a reduction
5914+
if check and alg_precision:
5915+
# Use the algorithm precision if it is available
5916+
# and not being ignored.
5917+
self._precision = alg_precision
59275918
else:
5928-
# This is a scalar that is not part of a reduction.
5929-
5930-
if check and alg_precision:
5931-
# Use the algorithm precision if it is available
5932-
# and not being ignored.
5933-
self._precision = alg_precision
5934-
else:
5935-
# Use default precision for this datatype if the
5936-
# algorithm precision is either not available or is
5937-
# being ignored.
5938-
self._precision = const.SCALAR_PRECISION_MAP[
5939-
self.intrinsic_type]
5919+
# Use default precision for this datatype if the
5920+
# algorithm precision is either not available or is
5921+
# being ignored.
5922+
self._precision = const.SCALAR_PRECISION_MAP[
5923+
self.intrinsic_type]
59405924

59415925
def _init_field_properties(self, alg_datatype, check=True):
59425926
'''Set up the properties of this field using algorithm datatype

src/psyclone/tests/domain/lfric/lfric_builtins_test.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
# POSSIBILITY OF SUCH DAMAGE.
3333
# -----------------------------------------------------------------------------
3434
# Author: A. R. Porter, STFC Daresbury Lab
35-
# Modified: I. Kavcic and O. Brunt, Met Office
35+
# Modified: I. Kavcic, O. Brunt and A. Pirrie, Met Office
3636
# Modified: R. W. Ford and N. Nobre, STFC Daresbury Lab
3737
# Modified: by J. Henrichs, Bureau of Meteorology
3838

@@ -1885,6 +1885,28 @@ def test_x_innerproduct_x(fortran_writer):
18851885
"asum = asum + f1_data(df) * f1_data(df)\n") in code
18861886

18871887

1888+
def test_x_innerproduct_x_r_double(fortran_writer, tmp_path):
1889+
''' Test the lower_to_language_level builtin methods for real64 precision.
1890+
1891+
'''
1892+
kern = builtin_from_file("15.9.3_X_innerproduct_X_builtin_r_double.f90")
1893+
assert str(kern) == "Built-in: X_innerproduct_X (real-valued field)"
1894+
1895+
# Test the 'lower_to_language_level()' method
1896+
lowered = kern.lower_to_language_level()
1897+
sum = lowered.scope.symbol_table.lookup("asum")
1898+
assert sum.datatype.precision.name == "r_double"
1899+
1900+
code = fortran_writer(lowered)
1901+
assert ("! Built-in: X_innerproduct_X (real-valued field)\n"
1902+
"asum = asum + f1_data(df) * f1_data(df)\n") in code
1903+
1904+
# Test compilation of generated code
1905+
psy, _ = get_invoke("15.9.3_X_innerproduct_X_builtin_r_double.f90",
1906+
api=API, idx=0, dist_mem=True)
1907+
assert LFRicBuild(tmp_path).code_compiles(psy)
1908+
1909+
18881910
def test_x_innerproduct_y(fortran_writer):
18891911
''' Test the metadata, str and lower_to_language_level builtin methods. '''
18901912
metadata = lfric_builtins.LFRicXInnerproductYKern.metadata()

src/psyclone/tests/domain/lfric/lfric_constants_test.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
# -----------------------------------------------------------------------------
3434
# Authors: R. W. Ford and A. R. Porter, STFC Daresbury Laboratory.
3535
# Modified by J. Henrichs, Bureau of Meteorology
36+
# A. Pirrie, Met Office
37+
3638

3739
'''
3840
Module containing tests for the LFRic constants class.
@@ -111,14 +113,18 @@ def test_precision_for_type():
111113
'''Check the precision_for_type() method.'''
112114
const = LFRicConstants()
113115
for module_info in const.DATA_TYPE_MAP.values():
114-
assert (const.precision_for_type(module_info["type"])
115-
== LFRicTypes(module_info["kind"].upper()))
116+
if module_info["type"] != "scalar_type":
117+
assert (const.precision_for_type(module_info["type"])
118+
== LFRicTypes(module_info["kind"].upper()))
116119

117120

118121
def test_precision_for_type_error():
119122
'''Tests that exceptions are raised as expected from
120123
precision_for_type().
121124
'''
125+
with pytest.raises(ValueError) as err:
126+
LFRicConstants().precision_for_type("scalar_type")
127+
assert "Cannot infer the precision of a 'scalar_type'." in str(err.value)
122128
with pytest.raises(InternalError) as err:
123129
LFRicConstants().precision_for_type("invalid")
124130
assert "Unknown data type 'invalid', expected one of" in str(err.value)

src/psyclone/tests/lfric_test.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1665,14 +1665,6 @@ class for a scalar reduction.
16651665
assert reduction._proxy_data_type is None
16661666
assert reduction._module_name == "scalar_mod"
16671667

1668-
# Scalar reduction with inconsistent precision (expects 'r_def')
1669-
arg = Arg("variable", None, None, ("real", "i_def"))
1670-
with pytest.raises(GenerationError) as info:
1671-
reduction._init_data_type_properties(arg)
1672-
assert ("This scalar is a reduction which assumes precision of type "
1673-
"'r_def' but the algorithm declares this scalar with precision "
1674-
"'i_def'" in str(info.value))
1675-
16761668
# Invalid reduction type (not a 'real')
16771669
arg = Arg("variable", None, None, ("integer", "i_def"))
16781670
with pytest.raises(GenerationError) as info:
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
! -----------------------------------------------------------------------------
2+
! BSD 3-Clause License
3+
!
4+
! Copyright (c) 2026, 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+
! Author: A. Pirrie, Met Office
35+
36+
program single_invoke
37+
38+
! Description: single point-wise operation (inner product of one field by
39+
! itself) specified in an invoke call of double precision.
40+
use constants_mod, only: r_double
41+
use field_mod, only: field_type
42+
43+
implicit none
44+
45+
type(field_type) :: f1
46+
real(r_double) :: asum
47+
48+
call invoke( X_innerproduct_X(asum, f1) )
49+
50+
end program single_invoke

0 commit comments

Comments
 (0)