From 911c861f30a6e18556ae025c01a1e0f7949e0752 Mon Sep 17 00:00:00 2001 From: Dom Heinzeller Date: Mon, 28 Sep 2026 09:04:21 -0600 Subject: [PATCH 1/2] Bug fix in capgen/generator/group_cap.py: use full access path for non-control variables in variable declarations so that DDT-components are found correctly --- capgen/generator/group_cap.py | 8 +++++++- unit-tests/test_suite_resolver.py | 21 ++++++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/capgen/generator/group_cap.py b/capgen/generator/group_cap.py index a6e0069d..a66c202a 100644 --- a/capgen/generator/group_cap.py +++ b/capgen/generator/group_cap.py @@ -33,6 +33,7 @@ ResolvedCall, ResolvedGroup, ResolvedSubcycle, + _render_value_expr, _root_symbol, iter_phase_calls, iter_phase_subcycles, @@ -179,7 +180,12 @@ def _dim_decl_local(dimensions: List[str], host_dict) -> str: locals_.append('{}:{}'.format(lb, ub)) else: entry = host_dict.get(std_name) if host_dict else None - locals_.append(entry.local_name if entry is not None else std_name) + # ``access_path``, not ``local_name`` so that a DDT-component dimension + # (``GFS_Control%levs`` for ``vertical_layer_dimension``) is resolved. + locals_.append( + _render_value_expr(entry, host_dict) + if entry is not None else std_name + ) return ', dimension({})'.format(', '.join(locals_)) diff --git a/unit-tests/test_suite_resolver.py b/unit-tests/test_suite_resolver.py index 86cd98e5..84ffb102 100644 --- a/unit-tests/test_suite_resolver.py +++ b/unit-tests/test_suite_resolver.py @@ -2693,12 +2693,31 @@ def test_horizontal_dimension_uses_chunk_bounds(self): ) def test_vertical_dim_uses_local_name(self): - # No special case for vertical dims — host's local name only. + # No special case for vertical dims. For a plain module-level host + # var the access path and the local name are the same string. self.assertEqual( _dim_decl_local(['vertical_layer_dimension'], self.hd), ', dimension(nlev)', ) + def test_ddt_component_dim_uses_full_access_path(self): + """A DDT-component dimension must be declared with the full DDT + walk. ``local_name`` alone (``levs``) names nothing in the group + cap's scope, so the temp is sized from an undefined symbol — the + transform's assignments were right and only its declaration wrong.""" + from metadata.variable_resolver import HostVarEntry + hd = dict(self.hd) + hd['vertical_layer_dimension'] = HostVarEntry( + 'vertical_layer_dimension', 'levs', 'GFS_Control%levs', + None, 'integer', '', 'count', [], False, False, '', + ) + self.assertEqual( + _dim_decl_local( + ['horizontal_dimension', 'vertical_layer_dimension'], hd, + ), + ', dimension(lb:ub, GFS_Control%levs)', + ) + def test_mixed_horiz_vert(self): self.assertEqual( _dim_decl_local( From aebe60055acae68e17e90be49a93d20a417860eb Mon Sep 17 00:00:00 2001 From: Dom Heinzeller Date: Thu, 1 Oct 2026 20:47:38 -0600 Subject: [PATCH 2/2] Apply suggestion from @climbfuji --- capgen/generator/group_cap.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/capgen/generator/group_cap.py b/capgen/generator/group_cap.py index a66c202a..ef02db51 100644 --- a/capgen/generator/group_cap.py +++ b/capgen/generator/group_cap.py @@ -180,8 +180,6 @@ def _dim_decl_local(dimensions: List[str], host_dict) -> str: locals_.append('{}:{}'.format(lb, ub)) else: entry = host_dict.get(std_name) if host_dict else None - # ``access_path``, not ``local_name`` so that a DDT-component dimension - # (``GFS_Control%levs`` for ``vertical_layer_dimension``) is resolved. locals_.append( _render_value_expr(entry, host_dict) if entry is not None else std_name