Skip to content

Commit

Permalink
Merge pull request #501 from ecmwf-ifs/nams-sfilter-fix
Browse files Browse the repository at this point in the history
SFilter: fix for external and ignored items
  • Loading branch information
reuterbal authored Mar 3, 2025
2 parents 57e4204 + 2510e71 commit 2f31d53
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 7 deletions.
13 changes: 7 additions & 6 deletions loki/batch/sfilter.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import networkx as nx

from loki.batch.item import Item, ExternalItem
from loki.tools import as_tuple


__all__ = ['SFilter']
Expand Down Expand Up @@ -60,12 +59,14 @@ def __iter__(self):

def __next__(self):
while node := next(self._iter):
# Determine the node type but skip externals if applicable
if isinstance(node, ExternalItem):
if self.include_external and node.origin_cls in as_tuple(self.item_filter):
# We found an ExternalItem that matches the item filter
break
continue
if isinstance(node, self.item_filter) and not (self.exclude_ignored and node.is_ignored):
if not self.include_external:
continue
node_cls = node.origin_cls
else:
node_cls = type(node)
if issubclass(node_cls, self.item_filter) and not (self.exclude_ignored and node.is_ignored):
# We found the next item matching the filter (and which is not ignored, if applicable)
break
return node
75 changes: 74 additions & 1 deletion loki/batch/tests/test_scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
CaseInsensitiveDict, graphviz_present
)
from loki.batch import (
Scheduler, SchedulerConfig, Item, ProcedureItem,
Scheduler, SchedulerConfig, Item, ProcedureItem, ModuleItem,
ProcedureBindingItem, InterfaceItem, TypeDefItem, SFilter,
ExternalItem, Transformation, Pipeline, ProcessingStrategy
)
Expand Down Expand Up @@ -3055,3 +3055,76 @@ def test_scheduler_indirect_import(frontend, tmp_path, enable_imports, import_le
assert global_a.type.dtype is BasicType.DEFERRED
assert global_a.type.initial is None
assert b_dtype.typedef is BasicType.DEFERRED

@pytest.mark.parametrize('frontend', available_frontends(skip={OMNI: "OMNI fails on missing module"}))
def test_scheduler_ignore_external_item(frontend, tmp_path):
fcode_driver = """
module driver_mod
contains
subroutine driver(nlon, klev, nb, ydml_phy_mf)
use parkind1, only: jpim, jprb
use kernel1_mod, only: kernel1
implicit none
type(model_physics_mf_type), intent(in) :: ydml_phy_mf
integer(kind=jpim), intent(in) :: nlon
integer(kind=jpim), intent(in) :: klev
integer(kind=jpim), intent(in) :: nb
integer(kind=jpim) :: jstart
integer(kind=jpim) :: jend
integer(kind=jpim) :: b
jstart = 1
jend = nlon
do b = 1, nb
call kernel1()
enddo
end subroutine driver
end module driver_mod
""".strip()
fcode_kernel1 = """
module kernel1_mod
contains
subroutine kernel1()
use parkind1, only: jpim, jprb
end subroutine kernel1
end module kernel1_mod
""".strip()

(tmp_path/'driver.F90').write_text(fcode_driver)
(tmp_path/'kernel1_mod.F90').write_text(fcode_kernel1)

config = {
'default': {
'mode': 'idem',
'role': 'kernel',
'expand': True,
'strict': True,
'ignore': ['parkind1'],
},
'routines': {
'driver': {'role': 'driver'}
}
}

class Trafo(Transformation):

item_filter = (ProcedureItem, ModuleItem)

def transform_module(self, module, **kwargs):
pass

def transform_subroutine(self, routine, **kwargs):
pass


definitions = ()
scheduler = Scheduler(paths=[tmp_path], config=SchedulerConfig.from_dict(config),
definitions=definitions, xmods=[tmp_path], frontend=frontend)

expected_items = {'driver_mod#driver', 'parkind1', 'kernel1_mod#kernel1'}
assert expected_items == {item.name for item in scheduler.items}
for item in scheduler.items:
if item.name == 'parkind1':
assert item.is_ignored
assert isinstance(item, ExternalItem)
# check whether this works without any error
scheduler.process(transformation=Trafo())

0 comments on commit 2f31d53

Please sign in to comment.