-
Notifications
You must be signed in to change notification settings - Fork 21
Test UnitsAspect update_payload procedures #4347
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
base: release/MAPL-v3
Are you sure you want to change the base?
Test UnitsAspect update_payload procedures #4347
Conversation
…date_from_payload - Tests for update_from_payload with ESMF_Field (R4, R8, I4, I8, MIRROR) - Tests for update_from_payload with ESMF_FieldBundle (R4, R8, MIRROR) - Tests for update_payload with ESMF_Field (R4, R8, I4, I8, MIRROR) - Tests for update_payload with ESMF_FieldBundle (R4, R8, MIRROR) - Round-trip tests to verify data integrity - Corner cases: no field/bundle provided, multiple consecutive updates - Tests for overwriting existing typekind values - Tests for proper mirror flag handling These tests ensure reliable operation of critical framework methods that synchronize TypekindAspect state with ESMF payloads.
- Add comprehensive test suite for TypekindAspect (19 tests) - Test update_payload() and update_from_payload() methods - Cover R4, R8, I4, I8, and MIRROR typekinds for Field and FieldBundle - Initialize with non-matching typekinds to avoid false positives - Refactor FieldBundleInfo to delegate typekind handling to FieldInfo - Removes duplicate to_string/to_TypeKind functions - Fixes MIRROR typekind support for bundles (was returning 200 instead of "<MIRROR>") - FieldInfoGetInternal/SetInternal now handle typekind parameter
- Created Test_UngriddedDimsAspect.pf with 18 tests covering: * Empty ungridded dimensions * Single and multiple ungridded dimensions * Mirror ungridded dimensions (documented FieldInfo layer bug) * Update operations in both directions (aspect ↔ payload) * Roundtrip and overwrite scenarios * Both Field and FieldBundle variants - Enhanced Test_UnitsAspect.pf from 4 to 14 tests covering: * Empty, simple, and compound units * Update operations in both directions * Roundtrip and overwrite scenarios * Both Field and FieldBundle variants - Test naming conventions follow TypekindAspect pattern - All tests passing (18/18 for UngriddedDims, 14/14 for Units) - Mirror tests include TODO notes documenting expected behavior once FieldInfo bug is resolved
| namespace_ = namespace | ||
| end if | ||
|
|
||
| isPresent=present(units) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the name isPresent is serving too many roles in this procedure. But don't change it unless I find other things that I want changed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I was concerned about that. I could have compressed it down to a single logical value like this:
isPresent = present(units) .and. units .and. ESMF_InfoIsPresent(info, key=full_key, _RC)
if(isPresent) then
...
end if
if I could force Fortran to evaluate it left to right. Even then, I needed a variable because for the _RC macro.
This may be out of date pending other decisions. If it stays in, I can reduce it down to a single assignment, which makes the block a little bit smaller. Unfortunately, I can't easily avoid the nested if blocks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You cannot force Fortran to evaluate left-to right.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Sorry - I missed your "if".)
| integer :: i | ||
|
|
||
| child = '' | ||
| s = trim(full_key) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this line is unnecessary? Can just use full_key in the expressions below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. The trim isn't necessary, either. I can just use full_key instead of the extra s variable or trim(full_key). I can push this up with an update.
|
|
||
| contains | ||
|
|
||
| subroutine field_remove(field, unusable, units, standard_name, long_name, rc) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feature is ultimately requiring a great deal of code for a relatively narrow corner case.
A bit late now, but I probably should have admitted that no one will ever set the mirror condition after having set it to something else. (Famous last words.)
More realistically it argues for always having a special value for the mirror case rather than using allocatable. My design overloads the responsibility of the ALLOCATABLE attribute: (1) used to indicate present/not-present and (2) mirror logic. (1) is a nice part of Fortran that works well here. (2) ... not so much.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The question then is do we want a derived type for Units (and a few other things in this category) or just a reserved string.
We will face the same issue soon with AttributesAspect, as StringVector() does not have a way to indicate mirror aside from not being allocated. (Empty string vector means "no relevant attributes".
Another issue I now see is what default do we want in VarSpec? When constructing a variable in a VarSpec, a missing "attributes" should mean empty attributes. A missing unit is more debatable, and probably currently shows as mirror. I think we need a consistent policy here, and that will drive the other stuff above. (I've known this concern was coming, but it was not a priority until now.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems there are two values in question. The first is the units component for the UnitsAspect derived type. The second is the units key/value map in the payload ESMF_Info object. (Of course, this generalizes to other aspects and their components.) We could continue with our strategy for the derived type component, but change the strategy for the ESMF_Info for the payload.
| UnitsAspect | <=> | Field Info | |
|---|---|---|---|
| CURRENT | units unallocated [is_mirror() ~ .TRUE.] |
<=> | Missing units key |
| PROPOSED | units unallocated [is_mirror() ~ .TRUE.] |
<=> | units: NULL * |
* In the Set direction, unallocated would map to units: NULL. In the Get direction, I think it would be better to map units: NULL to units unallocated and map missing units key to units unallocated as well. It would not be one-to-one, and purists would object, but I think it would be OK, since we don't need to recover the original Info object value once the units component is updated from the payload.
unallocated [is_mirror()] -> key: NULL
key: NULL -> units unallocated
missing units key -> units unallocated
I will think about this over lunch, and check on NULL in ESMF_Info objects. Also, I am thinking about a signal value to represent unset, but as we have seen before, we have to be very careful that the signal value will not collide with valid values. (So ``, unset and `NULL` (literal string) are not good.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On further research, NULL may not be the right strategy. It would require calling ESMF_InfoSetNULL instead of ESMF_InfoSet (through MAPL_FieldSet). That adds complexity. I think it would be better to encode the unset status in the string that we read/write for units and similar Info objects. It would allow it to be handled differently for different components. We could have a character parameter variable that is shared. That would be our standard value in Info objects for character values (scalar) that are not set. In this case, it would look like this:
aspect%units not allocated -> units: UNSET
units: UNSET -> aspect%units not allocated
units not present -> aspect%units not allocated
The question remains what is the value of UNSET (or whatever variable name we come up with.) One possibility is ASCII NUL. It conveys a different meaning than "NULL" or "", and it is hard to imagine that a user would ever want to use that as a character value. We could use an unlikely combination of ASCII symbol characters, but we would need to choose carefully. In the context of units, it would not be difficult to pick that, but if we want a general Fortran character parameter variable to represent any unset character value in an Info object, we need to be more careful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a followup question. But easier to ask by voice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, maybe I can state it in writing. I think we still have to allow the units key to be simply missing in the info object. E.g., if someone uses a noncanonical construction of a Field, and never mention units, there will be no way to give it the "null" value in info in the first place.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also for the MIRROR semaphore we have lots of options. lots of special characters cannot be used in actual units. (Should verify that.) So it might be useful to use a string that is humanly meaningful so that when you print the info you can understand it.
Currently we have "" meaning it has units but don't try converting them. And now we could have "". I'm quite open to the actual spelling here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note for me: We will use a string to indicate the mirror status. The string will be visible ASCII characters that are meaningful to humans, but it will include ASCII symbol characters to prevent collision with valid units. The characters will not be +, -, or _.
tclune
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically I approve. But you'll see in the comments, that we may want to consider a different path here.
Types of change(s)
Checklist
make tests)Description
This PR:
Related Issue