Skip to content

Commit 827f725

Browse files
authored
Merge branch 'main' into no-xios-logging
2 parents f14d509 + 159c1f5 commit 827f725

15 files changed

Lines changed: 326 additions & 133 deletions

CONTRIBUTORS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
| thomasmelvin | Thomas Melvin | Met Office | 2026-01-15 |
3030
| stevemullerworth | Steve Mullerworth | Met Office | 2026-01-28 |
3131
| ericaneininger | Erica Neininger | Met Office | 2026-03-02 |
32+
| RobWatersMet | Rob Waters | University of Cambridge | 2026-03-24 |
33+
| mo-lucy-gordon | Lucy Gordon | Met Office | 2026-03-11 |
34+
| iboutle | Ian Boutle | Met Office | 2026-03-04 |
3235
| ricky-lv426 | Ricky Olivier | University of Exeter | 2026-01-12 |
3336
| mo-alistairp | Alistair Pirrie | Met Office | 2026-01-19 |
3437
| yaswant | Yaswant Pradhan | Met Office | 2025-12-16 |

applications/lfric_atm/build/psyclone_transmute_file_list.mk

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export PSYCLONE_PHYSICS_FILES = \
2525
gw_ussp_mod \
2626
imp_mix \
2727
jules_exp_kernel_mod \
28-
jules_extra_kernel_mod \
28+
jules_extra_kernel_mod \
2929
jules_imp_kernel_mod \
3030
kmkh \
3131
kmkhz_9c_wtrac \
@@ -37,12 +37,14 @@ export PSYCLONE_PHYSICS_FILES = \
3737
pc2_initiation_kernel_mod \
3838
pc2_conv_coupling_kernel_mod \
3939
sw_kernel_mod \
40-
sw_rad_tile_kernel_mod \
41-
tr_mix \
42-
ukca_aero_ctl \
40+
ukca_aero_ctl \
41+
ukca_abdulrazzak_ghan \
4342
ukca_chemistry_ctl_full_mod \
44-
ukca_main1-ukca_main1
45-
43+
ukca_main1-ukca_main1 \
44+
sw_rad_tile_kernel_mod \
45+
jules_imp_kernel_mod \
46+
jules_exp_kernel_mod \
47+
jules_extra_kernel_mod
4648

4749
##### TRANSMUTE_INCLUDE_METHOD specify_include #####
4850

@@ -60,7 +62,7 @@ export PSYCLONE_PASS_NO_SCRIPT = ukca_abdulrazzak_ghan
6062
# These files will be filtered, and will NOT be run through PSyclone.
6163

6264
# Directories to psyclone
63-
export PSYCLONE_DIRECTORIES = science/ukca
65+
export PSYCLONE_DIRECTORIES =
6466

6567
# A general file exception list
6668
export PSYCLONE_PHYSICS_EXCEPTION =

applications/lfric_atm/optimisation/azngarch-sandbox/transmute/science/ukca/src/science/core/chemistry/ukca_chemistry_ctl_full_mod.py

Lines changed: 127 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
# The file LICENCE, distributed with this code, contains details of the terms
44
# under which the code may be used.
55
##############################################################################
6-
76
# Summary
87
# =======
98
#
@@ -45,6 +44,19 @@
4544
# * fulldom_size_name: name of variable holding full-domain size
4645
# * asad_call_name: name of the top-level ASAD solver routine
4746
#
47+
# OpenMP can also be added to the chunked loop by setting the environment
48+
# variable UKCA_FULL_CHUNK_OMP to True. By default it will be turned on
49+
# provided the chunk size is not equal to domain size, i.e. loop of length 1
50+
#
51+
# OpenMP parallelism is then added to the chunking loop using an omp parallel do
52+
# directive to allow for top level parallelism on the ASAD solver. Importantly
53+
# a call to ukca_reallocate_asad_arrays which reallocates the THREADPRIVATE
54+
# arrays. This is done within the parallel region to account for the potential
55+
# for chunk_size to be different between iterations, i.e. smaller last
56+
# iteration. Dynamic scheduling has been selected based upon the number of
57+
# solver iterations varying between chunks depending on the complexity of the
58+
# chemistry.
59+
#
4860
# Example
4961
# =======
5062
#
@@ -98,16 +110,40 @@
98110
# =======
99111

100112
import os
101-
102-
from psyclone.version import (__MAJOR__, __MINOR__, __MICRO__)
113+
import logging
103114
from psyclone.psyir.nodes import (
104-
ArrayReference, Assignment, BinaryOperation, Call, IntrinsicCall,
105-
Literal, Loop, Routine, Reference, Schedule)
115+
ArrayReference,
116+
Assignment,
117+
BinaryOperation,
118+
Call,
119+
IfBlock,
120+
IntrinsicCall,
121+
Literal,
122+
Loop,
123+
Reference,
124+
Routine,
125+
Schedule,
126+
UnaryOperation,
127+
)
106128
from psyclone.psyir.symbols import (
107-
INTEGER_TYPE, REAL_TYPE, CHARACTER_TYPE, Symbol, DataSymbol, ArrayType,
108-
RoutineSymbol)
129+
CHARACTER_TYPE,
130+
INTEGER_TYPE,
131+
REAL_TYPE,
132+
ArrayType,
133+
ContainerSymbol,
134+
DataSymbol,
135+
ImportInterface,
136+
RoutineSymbol,
137+
Symbol,
138+
)
109139
from psyclone.psyir.transformations.reference2arrayrange_trans import (
110-
Reference2ArrayRangeTrans)
140+
Reference2ArrayRangeTrans,
141+
)
142+
from psyclone.transformations import OMPParallelLoopTrans, TransformationError
143+
from psyclone.version import __MAJOR__, __MICRO__, __MINOR__
144+
145+
# Conditonal imports
146+
# ==================
111147

112148
psy_version = (__MAJOR__, __MINOR__, __MICRO__)
113149

@@ -128,9 +164,22 @@
128164
# Name of the routine in which to apply the transformation
129165
routine_name = "ukca_chemistry_ctl_full"
130166

131-
# Transformation
167+
# Source and name of the reallocation routine
168+
asad_realloc_routine = ("ukca_chemistry_ctl_col_mod",
169+
"ukca_reallocate_asad_arrays")
170+
171+
172+
# Utility
132173
# ==============
174+
def get_bool_env(var_name: str, default: bool = False) -> bool:
175+
val = os.getenv(var_name)
176+
if val is None:
177+
return default
178+
return val.strip().lower() in ('1', 'true', 't', 'yes', 'y', 'on')
179+
133180

181+
# Transformation
182+
# ==============
134183

135184
def trans(psyir):
136185
desired_chunk_size = os.getenv("UKCA_FULL_CHUNK_SIZE")
@@ -149,6 +198,12 @@ def trans(psyir):
149198
message_text = ("UKCA full-domain chunking enabled with " +
150199
"a chunk size of " + desired_chunk_size)
151200

201+
use_omp = get_bool_env("UKCA_FULL_CHUNK_OMP", True)
202+
if desired_chunk_size is None and use_omp:
203+
logging.WARNING(
204+
"Turning off omp as chunk size is set to full domain size")
205+
use_omp = False
206+
152207
# Locate correct routine within which to apply the transformation
153208
for routine in psyir.walk(Routine):
154209
if routine.name != routine_name:
@@ -348,3 +403,66 @@ def trans(psyir):
348403
# -------------------------
349404

350405
loop.parent.addchild(assign_desired_chunk_size, index=loop.position)
406+
407+
if use_omp:
408+
# Add import for ASAD reallocation routine
409+
# ----------------------------------------
410+
411+
asad_realloc_mod_sym = ContainerSymbol(asad_realloc_routine[0])
412+
routine.symbol_table.add(asad_realloc_mod_sym)
413+
asad_realloc_routine_sym = Symbol(asad_realloc_routine[1])
414+
asad_realloc_routine_sym.interface = ImportInterface(
415+
asad_realloc_mod_sym)
416+
routine.symbol_table.add(asad_realloc_routine_sym)
417+
418+
# Add Reallocation Call to within Loop
419+
# ------------------------------------
420+
# Create reallocation call
421+
realloc_call = Call()
422+
realloc_call.addchild(Reference(RoutineSymbol(
423+
asad_realloc_routine[1])))
424+
realloc_call.addchild(Reference(chunk_size_var))
425+
426+
# Create conditional reallocation call
427+
realloc_block = IfBlock.create(
428+
BinaryOperation.create(
429+
BinaryOperation.Operator.OR,
430+
UnaryOperation.create(
431+
UnaryOperation.Operator.NOT,
432+
IntrinsicCall.create(
433+
IntrinsicCall.Intrinsic.ALLOCATED,
434+
[Reference(
435+
Symbol(next(iter(asad_vars.keys()))))])),
436+
BinaryOperation.create(
437+
BinaryOperation.Operator.NE,
438+
Reference(chunk_size_var),
439+
IntrinsicCall.create(
440+
IntrinsicCall.Intrinsic.SIZE,
441+
[Reference(Symbol(next(iter(asad_vars.keys())))),
442+
("dim", Literal("1", INTEGER_TYPE))]))),
443+
[realloc_call])
444+
445+
loop.loop_body.addchild(realloc_block, index=2)
446+
447+
# Added OMP transformation on desired loop
448+
# ----------------------------------------
449+
450+
omp_trans = OMPParallelLoopTrans(omp_schedule="static")
451+
opts = {
452+
# some non-PURE subroutines called within this loop
453+
"force": True,
454+
# several WRITE statements used for diagnostics
455+
"node-type-check": False,
456+
}
457+
458+
try:
459+
omp_trans.apply(
460+
loop, options=opts,
461+
)
462+
463+
except TransformationError as err:
464+
err_msg = ("ukca_chemistry_ctl_full_mod.py: Error: "
465+
"could not apply OMP transformation "
466+
f"to loop: {err.message_text}")
467+
468+
raise TransformationError(err_msg) from err

0 commit comments

Comments
 (0)