Skip to content

Conversation

@mo-rickywong
Copy link
Contributor

@mo-rickywong mo-rickywong commented Dec 10, 2025

PR Summary

Sci/Tech Reviewer: @allynt
Code Reviewer: @MatthewHambley

This PR is to allow users more direct access to the namelist configuration values from
Fortran object (rather than global module scope) while maintaining it's read-only nature.
e.g.
modeldb%config%<MyNamelist>%MyNamelistMember()

This PR is linked to LFRic-core trac ticket #4702, which provides more details on the change itself

Code Quality Checklist

(Some checks are automatically carried out via the CI pipeline)

  • I have performed a self-review of my own code
  • My code follows the project's
    style guidelines
  • Comments have been included that aid understanding and enhance the
    readability of the code
  • My changes generate no new warnings

Testing

  • I have tested this change locally, using the LFRic Core rose-stem suite
  • If required (eg. API changes) I have also run the LFRic Apps test suite
    using this branch
  • If any tests fail (rose-stem or CI) the reason is understood and
    acceptable (eg. kgo changes)
  • I have added tests to cover new functionality as appropriate (eg. system
    tests, unit tests, etc.)
  • Any new tests have been assigned an appropriate amount of compute resource
    and have been allocated to an appropriate testing group (i.e. the
    developer tests are for jobs which use a small amount of compute resource
    and complete in a matter of minutes)

trac.log

Security Considerations

  • I have reviewed my changes for potential security issues
  • Sensitive data is properly handled (if applicable)
  • Authentication and authorisation are properly implemented (if applicable)

Performance Impact

  • Performance of the code has been considered and, if applicable, suitable
    performance measurements have been conducted

AI Assistance and Attribution

  • Some of the content of this change has been produced with the assistance
    of Generative AI tool name (e.g., Met Office Github Copilot Enterprise,
    Github Copilot Personal, ChatGPT GPT-4, etc) and I have followed the
    Simulation Systems AI policy
    (including attribution labels)

Documentation

  • Where appropriate I have updated documentation related to this change and
    confirmed that it builds correctly

PSyclone Approval

  • If you have edited any PSyclone-related code (eg. PSyKAl-lite, Kernel
    interface, optimisation scripts, LFRic data structure code) then please
    contact the
    tooscollabdevteam@metoffice.gov.uk

Sci/Tech Review

  • I understand this area of code and the changes being added
  • The proposed changes correspond to the pull request description
  • Documentation is sufficient (do documentation papers need updating)
  • Sufficient testing has been completed

Please alert the code reviewer via a tag when you have approved the SR

Code Review

  • All dependencies have been resolved
  • Related Issues have been properly linked and addressed
  • CLA compliance has been confirmed
  • Code quality standards have been met
  • Tests are adequate and have passed
  • Documentation is complete and accurate
  • Security considerations have been addressed
  • Performance impact is acceptable

@mo-rickywong mo-rickywong requested a review from a team as a code owner December 10, 2025 13:38
@mo-rickywong mo-rickywong requested review from MatthewHambley and removed request for a team December 10, 2025 13:38
@github-actions github-actions bot added the cla-required CLA signature is required for this PR. label Dec 10, 2025
@github-actions github-actions bot added cla-signed This contributor has signed the CLA. and removed cla-required CLA signature is required for this PR. labels Dec 11, 2025
Copy link
Collaborator

@MatthewHambley MatthewHambley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I notice that across the board you assign namelist values to variables before using them. Can you confirm this is a choice you've made and that, as functions, they can be used in-line. e.g. call something(value, modeldb%config%my_namelist%other_value().

Yes this is a choice, the values can be accessed in-line. I have extracted them as the variables existed and shortens the actual code so it appears cleaner.

-----
The Configurator provides several python scripts found in
``infrastructure/build/tools``. Each of these scripts generate
Fortran source code that is specific to an applications metadata.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Fortran source code that is specific to an applications metadata.
Fortran source code that is specific to an application's metadata.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This conversation can be closed, the suggestion was applied to branch

Copy link
Collaborator

@MatthewHambley MatthewHambley Dec 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I presume there is some deprecation around things appearing in this document. A note of that would be helpful. What is the preferred way, what is deprecated?

The documentation has a section on deprecated process. I'll review this file for deprecated bits

In general, applications will only require one ``config_type`` object.
Should an application require to read more than one configuration file
in a model run, another ``config_type`` will be required,
`i.e.` 1 ``config_type`` object/configuration file.
Copy link
Collaborator

@MatthewHambley MatthewHambley Dec 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the last line trying to say? Do you mean one config_type per configuration file?

yes, was trying to explain without pointing the finger at specific groups.

Copy link
Contributor Author

@mo-rickywong mo-rickywong Jan 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was removed/relocated so that the multiple configuration issue is referred to under loading the configuration

source_partitioner)
call destination_partitioning_nml%get_value('partitioner', &
destination_partitioner)
call iter%initialise(config%partitioning)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there an issue for providing a convenience function to directly recover a namelist by key? Are there problems with providing such a convenience function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No problem I don't think, it was rejected at the team meeting when discussed, though lfricinputs are aparently trying to do this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue #197 created for this

namelists may have multiple instances or when an application wishes
to load multiple configuration files. It is recommended that access
to configuration namelists be limited to usage of the ``modeldb%config``
item described above.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may be the place to put an actual date on when the old implementation will be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather not put a date on here yet, until we have a fair idea that the rest of the piecemeal changes are just cranking the handle. Attempts to update the LFRic_apps repo present some issues that I'd like to iron out before putting a date in that might change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, changed my mind on that, put a date of April 2026, so we can pull the the plug on it any time after.

Comment on lines 124 to 125
!> @param [in] namelist The namelist that is to be added
!> into the collection.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there something more useful to be said about the namelist, rather than repeating the brief description? Are there any restrictions or requirements on it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated, the namelist type needs to be one that is defined in the application metadata otherwise it won't be installed in the config object.

character(str_def) :: full_name

! Check namelist name is valid, if not then exit with error
full_name = namelist_obj%get_full_name()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can strings be handled as character(:), allocatable thereby holding only the payload? Remember allocatable character arrays are magic and work with the = operator much better than any other type of allocatable.

Comment on lines +159 to +163
{% endif %}
{%- endfor %}

{%- for i in range(namelists|length) %}
{%- if duplicates[i] %}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be done as one loop? Loop over namelists, if duplicates is true, do one thing, else (it's false) do the other.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could, though it was done this way so that all the namelists that allow multiple instances are grouped together in the resulting config_type definition.


end function {{parameter.name}}

{%- else %}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be good to add a comment to else clauses which gives the logic which triggers it, in this case name not in arrays. If Jinja allows for comments within curly brackets.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments added

$(Q)mkdir -p $(dir $@)
$(Q)$(LFRIC_BUILD)/tools/GenerateLoader $(VERBOSE_ARG) $@ $(shell cat $(CONFIG_DIR)/config_namelists.txt)

$(Q)touch $(WORKING_DIR)/duplicate_namelists.txt
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might move this down to where it is used, unless it is secretly used by GenerateConfigLoader and GenerateExtendedNamelistType.

Copy link
Contributor Author

@mo-rickywong mo-rickywong Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved it earlier on, to after GenerateNamelistLoader. this script will produce duplicate_namelists.txt. The touch is to ensure that is a file to find for GenerateConfigType

Copy link
Collaborator

@MatthewHambley MatthewHambley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not too many changes, some of which may be postponed to later sets.

Comment on lines +38 to +40
$(Q)$(LFRIC_BUILD)/tools/GenerateNamelistLoader \
$(VERBOSE_ARG) \
$(CONFIG_DIR)/rose-meta.json \
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're reformatting this command please pick a continuation marker style and stick with it. Either marker goes immediately after the end of the line (with a space) or they are lined up. This seems to be neither.


def __init__(self, intrinsic_type: str, kind: str, write_format: str):
"""
:param intrinsic_type: One of "integer", "real", etc.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is a set list, why not use an Enum?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I follow fully, this file is a duplicate of namelistdescription.py with some changes for the extended namelist. I don't fully understand the query, though I assume it would also apply to the original namelistdescription.py file. So I guess the author of that file would know better than I.


_singletonMap: Dict[str, Dict[str, Dict[str, "FortranType"]]] = {}

def __init__(self, intrinsic_type: str, kind: str, write_format: str):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Kind" probably needs to be optional as we do not require one with integers.

"""
Gets the type designator used by declarations in source files.
"""
return f"{self.intrinsic_type}({self.kind})"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will need to take into account optional kinds.

"""
Gets a label for this type.
"""
return f"{self.intrinsic_type}_{self.kind}"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kind may be optional.

Comment on lines +110 to +117
select type(namelist_obj)
class default
write(log_scratch_space, '(A)') &
' Undefined namelist type(' // trim(name) // &
'), for this configuration.'
call log_event(log_scratch_space, log_level_error)

end select
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't you want to make this check before trying to dereference the object to get the various name strings?

!> @brief Queries config_type for the total number of namelists stored.
!> @return answer The number of namelists stored
!=====================================================================
function n_namelists(self) result(answer)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While words for symbol names.

implicit none

class(config_type), intent(in) :: self
character(str_def) :: answer
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
character(str_def) :: answer
character(:), allocatable :: answer

There is magic around assigning strings which means this should work.


character(*), optional, intent(in) :: listname

character(str_def), allocatable :: namelist_names(:)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you are correct that you cannot have allocatable arrays of allocatable values. It's all covered in the documentation you are down to review at MetOffice/Technical-Knowledgebase#5.

if (allocated(self%nml_fullnames)) deallocate(self%nml_fullnames)

self%config_name = cmdi
self%isinitialised = .false.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Normally "clear" semantics would not de-initialise the object. That would be something the destructor would do. Is there a reason for it here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed This contributor has signed the CLA.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants