Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add optional attribute to Capgen #529

Merged
merged 24 commits into from
Mar 8, 2024

Conversation

dustinswales
Copy link
Collaborator

@dustinswales dustinswales commented Jan 30, 2024

Description

This PR adds support to use the fortran optional attribute at the scheme level in Capgen. This functionality does not replace the active attribute, but rather builds on it.

Previously, conditionally allocated fields needed by a scheme were required to be accompanied with the allocation logic defined by the host (e.g the "active" condition). With this change, the scheme can internally query the "presence" instead of carrying the host model logic "down into the scheme".

The following modifications were made:

  • Metadata parsing: Check for compatibility between scheme and host metadata. If host has inactive variable, ensure that scheme has variable declared as optional.
  • Fortran parsing: Check for consistency between metadata and fortran file. If fortran file does not contain the optional attribute in its declaration, report error.
  • For any optional scheme variable, add optional attribute to cap level declarations.
  • Declare null pointer at cap level when host does not use optional scheme variable

Fixes:

Addresses #527 (new test for optional variable) and partially #526 (support for optional attribute in Capgen)

Testing:
test removed:
unit tests:
system tests: The var_compatibility_test was expanded, built on top of #525, to test this feature.
manual testing:

@dustinswales
Copy link
Collaborator Author

@gold2718 @peverwhee @nusbaume
I think that this does almost all that we want it to do. Feel free to take a gander.
There's one piece that I'm not sure about? What needs to be done to add support to pass chunks of contiguous arrays? @climbfuji

@climbfuji
Copy link
Collaborator

@gold2718 @peverwhee @nusbaume I think that this does almost all that we want it to do. Feel free to take a gander. There's one piece that I'm not sure about? What needs to be done to add support to pass chunks of contiguous arrays? @climbfuji

In the caps, we need to declare a pointer for each variable with an active attribute that either points to a valid chunk of the contiguous array if the variable is active (based on the active condition), or is passed as a null pointer if the active-attribute condition is evaluated as .false.

@dustinswales
Copy link
Collaborator Author

@gold2718 @DomHeinzeller I'm close to having this working, just one smallish hold up.

Do either of you two know how to change the local_name of a dummy argument in a call_list?
I need to go from, call sub(var=var_local) => call sub(var=var_local_ptr)

@dustinswales
Copy link
Collaborator Author

@DomHeinzeller @gold2718 @peverwhee @nusbaume
This one is ready for review
I still need to chase down a failing unit test, but the system tests are working (I probably changed a function call and broke an interface in the unit tests)

@dustinswales
Copy link
Collaborator Author

Snippets of auto-generated caps:
Screenshot 2024-02-08 at 11 43 54 AM

Screenshot 2024-02-08 at 11 44 45 AM

Copy link
Collaborator

@climbfuji climbfuji left a comment

Choose a reason for hiding this comment

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

This looks great! Only a few minor comments

scripts/suite_objects.py Outdated Show resolved Hide resolved
scripts/suite_objects.py Show resolved Hide resolved
scripts/suite_objects.py Show resolved Hide resolved
scripts/suite_objects.py Outdated Show resolved Hide resolved
scripts/suite_objects.py Outdated Show resolved Hide resolved
test/var_compatibility_test/run_test Outdated Show resolved Hide resolved
test/var_compatibility_test/test_host_data.meta Outdated Show resolved Hide resolved
Copy link
Collaborator

@climbfuji climbfuji left a comment

Choose a reason for hiding this comment

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

I have one doctest failure and a suggestion for a fix, other than that I am happy with the changes. (I ran doctests, all tests in test/ and also all tests in test_prebuild.

scripts/metavar.py Show resolved Hide resolved
scripts/metavar.py Outdated Show resolved Hide resolved
dustinswales and others added 2 commits February 22, 2024 14:53
Co-authored-by: Dom Heinzeller <dom.heinzeller@icloud.com>
Copy link
Collaborator

@climbfuji climbfuji left a comment

Choose a reason for hiding this comment

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

Thanks! doctests are now ok

Copy link
Collaborator

@peverwhee peverwhee left a comment

Choose a reason for hiding this comment

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

Nice work, @dustinswales !

A couple comments/questions

scripts/ccpp_capgen.py Outdated Show resolved Hide resolved
scripts/metavar.py Outdated Show resolved Hide resolved
scripts/metavar.py Outdated Show resolved Hide resolved
scripts/suite_objects.py Show resolved Hide resolved
scripts/suite_objects.py Show resolved Hide resolved
scripts/suite_objects.py Show resolved Hide resolved
scripts/suite_objects.py Outdated Show resolved Hide resolved
scripts/suite_objects.py Show resolved Hide resolved
scripts/suite_objects.py Show resolved Hide resolved
test/var_compatibility_test/effr_calc.meta Outdated Show resolved Hide resolved
Copy link
Collaborator

@peverwhee peverwhee left a comment

Choose a reason for hiding this comment

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

thanks @dustinswales !

@climbfuji
Copy link
Collaborator

@gold2718 Would you like to review the PR or should we go ahead and merge? Thanks!

@climbfuji
Copy link
Collaborator

We need to merge this so that I can bring feature/capgen down to main. That's needed, because ccpp_prebuild uses the capgen metadata parser and I need the updates for the mandatory optional attribute for schemes if the host model has an active attribute with a value other than the default .true.. Once I've got that update, I can make the optional var changes in prebuild similar to this PR for capgen, which will unblock the transition to contiguous arrays instead of blocked DDTs for the UFS.

@gold2718
Copy link
Collaborator

gold2718 commented Mar 6, 2024

We need to merge this so that I can bring feature/capgen down to main. That's needed, because ccpp_prebuild uses the capgen metadata parser and I need the updates for the mandatory optional attribute for schemes if the host model has an active attribute with a value other than the default .true.. Once I've got that update, I can make the optional var changes in prebuild similar to this PR for capgen, which will unblock the transition to contiguous arrays instead of blocked DDTs for the UFS.

Is there time to submit at least comments from partial reviews in progress?

@climbfuji
Copy link
Collaborator

We need to merge this so that I can bring feature/capgen down to main. That's needed, because ccpp_prebuild uses the capgen metadata parser and I need the updates for the mandatory optional attribute for schemes if the host model has an active attribute with a value other than the default .true.. Once I've got that update, I can make the optional var changes in prebuild similar to this PR for capgen, which will unblock the transition to contiguous arrays instead of blocked DDTs for the UFS.

Is there time to submit at least comments from partial reviews in progress?

Oh yes, for sure. Just wanted everyone to know why we need to get his in soon. Thanks for reviewing.

Copy link
Collaborator

@gold2718 gold2718 left a comment

Choose a reason for hiding this comment

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

This is not as thorough as usual for me, mainly because I have not found the time to go through the suite_objects logic in detail. However, it seems okay at the level I understand and the generated code is okay (meaning you get what you were looking for) so 👍
I do have a couple of questions and some suggestions if there is time for those.

Comment on lines 24 to 32
real(kind_phys), intent(in),optional :: effrg_in(:,:)
real(kind_phys), intent(in),optional :: ncg_in(:,:)
real(kind_phys), intent(out),optional :: nci_out(:,:)
real(kind_phys), intent(inout) :: effrl_inout(:,:)
real(kind_phys), intent(out) :: effri_out(:,:)
real(kind_phys), intent(out),optional :: effri_out(:,:)
real(8),intent(inout) :: effrs_inout(:,:)
logical, intent(in) :: has_graupel
real(kind_phys), intent(out),optional :: ncl_out(:,:)
character(len=512), intent(out) :: errmsg
integer, intent(out) :: errflg
Copy link
Collaborator

Choose a reason for hiding this comment

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

It is pretty non standard to have non-optional arguments follow optional arguments in a Fortran subprogram. This is because "there must be no further positional arguments after the first keyword argument."
This 'works' in the CCPP because we generate caps that use keywords for every argument (thanks @davegill), however, I think it is still good practice to write portable code.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I agree this is ugly, and will fix, but I believe the standard in this case is referring to the argument list, not the declarations within the procedure.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Right but for instance, errmsg and errflg are not optional but show up in the argument list after effrg_in, effri_out, and others.

Copy link
Collaborator

Choose a reason for hiding this comment

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

This is something we've done consistently - always have errmsg and errflg at the very end. This is even more compelling if we think about the metadata order and the requirement (not sure if it's enforced in capgen, it isn't yet in prebuild) to have the same order as the argument list. Keeping those non-physics and purely framework related variables at the end would be nice.

Since nobody should be calling CCPP-compliant schemes directly - i.e. without ccpp-framework - we can rely on the arguments being listed as keywords?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Or, alternatively, move the framework-mandated variables to the very beginning? An awful lot of changes in the current schemes in the physics, but doable.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Since nobody should be calling CCPP-compliant schemes directly - i.e. without ccpp-framework - we can rely on the arguments being listed as keywords?

At the very least, make this a bold part of the documentation about optional variables. Anyone creating a new scheme can put the variables in any order and anyone is free to use current schemes outside of the CCPP but we should at least document the consequences.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I created issue #544 for that.

scripts/metavar.py Show resolved Hide resolved
intent_str = 'allocatable '
if target:
intent_str = 'allocatable,'
intent_str += ' target'
else:
intent_str = ' '*13
# end if
elif intent is not None:
alloval = self.get_prop_value('allocatable')
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 True here given the elif allocatable above? If it can, then what if is also optional?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'm not sure of the purpose of alloval here?
If we are in this block of code, the variable is not an allocatable?

scripts/suite_objects.py Outdated Show resolved Hide resolved
scripts/suite_objects.py Show resolved Hide resolved
scripts/suite_objects.py Outdated Show resolved Hide resolved
scripts/suite_objects.py Outdated Show resolved Hide resolved
dustinswales and others added 4 commits March 6, 2024 10:03
Co-authored-by: goldy <1588651+gold2718@users.noreply.github.com>
Co-authored-by: goldy <1588651+gold2718@users.noreply.github.com>
Co-authored-by: goldy <1588651+gold2718@users.noreply.github.com>
@climbfuji
Copy link
Collaborator

I also created #545 so that I can go ahead and merge this.

@climbfuji climbfuji merged commit c546cca into NCAR:feature/capgen Mar 8, 2024
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants