-
Notifications
You must be signed in to change notification settings - Fork 134
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
Refactor optional argument implementation for isotopes, snwgrain, therm1 and therm2 #423
Conversation
- Use argcheck design - Eliminate local copies of optional data - Pass optional arguments down the calling tree - Some minor format cleanup
This refactors the isotope implementation using the newer design, passing optional arguments down the calling tree and using the argcheck design. If this seems reasonable, I will refactor other Icepack features in a similar way where reasonable. Do we want a PR for each feature refactor or just one (or a few) PRs to cover multiple feature refactors? Would like to get some feedback before moving forward. This should be bit-for-bit and has no impact on the public interfaces. Will run comprehensive tests to confirm TBD. |
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 for not responding to the email. This looks fine to me.
uvel=l_uvel, vvel=l_vvel, & | ||
Uref=l_Uref, zlvs=zlvs) | ||
Qa_iso=Qa_iso, & | ||
Qref_iso=Qref_iso, & |
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.
What happens if present(Qref_iso)=F? Is this robust across all compilers/platforms? You probably tested that previously...
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 is robust. The optional attribute and "present" state is passed down the calling tree. As long as optional is set in the calling routine for this field if want to check it's "present" state (determined by the original caller) and/or the optional argument is not used unless it exists, all should be fine. You can definitely get into trouble if you pass the optional argument down the calling tree and use it if it wasn't passed. Hopefully, we'll avoid that with the logic we have setup.
One or a few to cover multiple features would be fine, but if something is particularly complicated, then just do that by itself. E.g. I imagine that the thermodynamics will be complicated, since there are many options that feed into it. |
…ocn, H2_16O_ocn, H2_18O_ocn - Modify fsloss optional argument implementation - Modify rsnwn, smicen, smliqn optional argument implementation
- Clean up some formatting
I think it may be worth reviewing and merging this now. Most of the therm1 and therm2 optional arguments have been refactored. Still waiting on some additional insight about meltsliq, but that can be done in a separate PR. |
Icepack and CICE test suites are bit-for-bit. |
columnphysics/icepack_atmo.F90
Outdated
!------------------------------------------------------------ | ||
! Check optional arguments | ||
! This is used for ocean and ice sfctype, need to be 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'm not sure I understand this comment, why does it say
This is used for ocean and ice sfctype
but then we just check sfctype == 'ice'
? What is "This" referring to?
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 atmo_boundary_layer
is also called from the ocean mixed layer routine, in which case the surface type that the atmosphere sees is ocean instead of ice. The mixed layer routine is not used for coupled simulations, usually, and isotopes might not be implemented in a separate ocean component model, which would then require some care 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.
I need to clean up this comment.
I think this is a nice clean up, it improves readability, I think. Also, gotta love a PR that removes more lines of code than it adds ;)
If I were doing it, I think I would probably do it that way:
This would be very much more pleasant to review, at least for me :) Also I would avoid changing the order of the variables attributes (like moving Thanks a lot for starting the work on this! :) |
columnphysics/icepack_atmo.F90
Outdated
!------------------------------------------------------------ | ||
|
||
if (sfctype == 'ice') then | ||
if (argcheck == 'always' .or. (argcheck == 'first' .and. first_call_ice)) then |
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 logic in this line is duplicated a few times. Would it make sense to isolate it to a function somewhere ? Then we could use
that function instead of the argcheck
variable.
The function could receive that boolean fist_call
(or here first_call_ice
) as argument and return a boolean...
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 that's a good idea, I'll take care of it.
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.
Just a few comments and questions -
I do worry a bit about Phil's comment here, regarding non-Fortran codes being able to use Icepack with Fortran keywords and optional arguments. What should we do about that?
do n = 1, n_iso | ||
ratio = c0 | ||
if (Qa_iso(2) > puny) ratio = Qa_iso(n)/Qa_iso(2) | ||
Qref_iso(n) = Qa_iso(n) - ratio*delq*fac |
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.
Farther down in the comments for this module, you say
You can definitely get into trouble if you pass the optional argument down the calling tree and use it if it wasn't passed.
So are Qa_iso and Qref_iso safe to use here without checking their 'present' status because the call to this subroutine isn't the first call in which those arguments are declared optional? It appears that you are checking it in what would be the first call into icepack, icepack_atm_boundary
. Is there some easy way to track when an optional argument needs to be checked 'if present' and when it doesn't? It's probably not as simple as just checking in icepack's interface routines.
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.
That's right, we have already checked the arguments in the highest level Icepack interface. So they are safe to use here without checking. That's our current design. As I mentioned the other day, there are pros and cons to doing it this way. A pro is that we check all the optional arguments early leveraging parameter flags and then we should be OK after that without having to check over and over. A negative is that you have to keep track of what's going on in different layers of the code.
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.
Okay, thank you.
columnphysics/icepack_atmo.F90
Outdated
!------------------------------------------------------------ | ||
! Check optional arguments | ||
! This is used for ocean and ice sfctype, need to be 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 think atmo_boundary_layer
is also called from the ocean mixed layer routine, in which case the surface type that the atmosphere sees is ocean instead of ice. The mixed layer routine is not used for coupled simulations, usually, and isotopes might not be implemented in a separate ocean component model, which would then require some care here.
columnphysics/icepack_snow.F90
Outdated
@@ -1194,6 +1194,7 @@ subroutine drain_snow (nslyr, vsnon, aicen, & | |||
else | |||
sliq = meltsliq ! computed in thickness_changes | |||
endif | |||
!tcx?? | |||
meltsliq = meltsliq |
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 line can be commented out. This section of the code was rewritten a bit and corrected, and this line was the logical culmination of that process.
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.
Do we want a PR for each feature refactor or just one (or a few) PRs to cover multiple feature refactors? Would like to get some feedback before moving forward.
If I were doing it, I think I would probably do it that way:
* 1 PR per module (so 1 per file) * In each PR, one commit per subroutine: removing `l_*` local variable, using `argcheck` to validate arguments, and adjusting calls to other subroutines if need be.
I don't think 1 PR per module will work well. The optional argument checking will depend on the underlying implementation and that needs to be coordinated. Removing the l_ variables might result in further optimizations down the calling tree. So maybe 1 PR per feature. I also understand about general cleanup (formatting) with updating features. I agree, it's just hard not to fix things when I see an opportunity, and I'm worried I may not circle back if I don't. I'll try to be more careful.
@@ -1852,15 +1853,15 @@ subroutine add_new_ice (ncat, nilyr, & | |||
enddo | |||
endif | |||
|
|||
frazil_conc = c0 |
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 line is still present in a similar section of code, above. The code is hard-wired for n_iso=3, apparently, so maybe this line should stay in case for some reason n_iso > 3?
(present(fswthru_vdf) .and. .not.present(fswthrun_vdf)) .or. & | ||
(present(fswthru_idr) .and. .not.present(fswthrun_idr)) .or. & | ||
(present(fswthru_idf) .and. .not.present(fswthrun_idf))) then | ||
call icepack_warnings_add(subname//' error in fswthru [iv]d[rf] arguments') |
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.
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's really the underlying implementation. The implementation in Icepack with this update will always computed the aggregated variables if they are passed, and that requires the category specific arguments too. We could change the implementation so both have to be passed for the category aggregate to be computed. The optional argument checking is determined to a large degree on the underlying implementation.
One option is for the non-Fortran interfaces to NOT adopt the optional arguments in their interfaces/uses. So non-Fortran might pass all arguments even if they are not needed. I don't actually know whether that will work for all languages, but we should explore as an appropriate time. I think for now, we should continue to add optional arguments moving forward. It provide backwards compatibility in the current community. If at some point in the future, we decide to not have optional arguments in icepack, we just remove the optional attribute on the Icepack interfaces and then update any interfaces in CICE/Icepack that do not conform. Everyone in the community would have to do the same, also anytime Icepacks is updated with any new arguments. That's the downside overall. I don't think we should abandon optional arguments until there is a clear reason to do so. |
The voice of reason - sounds good to me. |
Looks like there are just a few minor changes that could be made here. @apcraig let us know when you're ready to merge. |
cheyenne was down this week and i'm away from home, should be able to make progress next few days. will update conversation when updates are ready. |
I've updated the PR and running a full test suite now. Added icepack_chkoptargflag logical function and cleaned up a few other things associated with comments above. Feel free to review, will report updated results in the next day or so. |
CICE testing is complete with latest changes and everything looks 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.
Thanks, latest version looks good!
PR checklist
Short (1 sentence) summary of your PR:
Refactor isotope implementation with respect to optional arguments
Developer(s):
apcraig
Suggest PR reviewers from list in the column to the right.
Please copy the PR test results link or provide a summary of testing completed below.
CICE is bit-for-bit on cheyenne, full test suite. https://github.com/CICE-Consortium/Test-Results/wiki/cice_by_hash_forks#0bf0fdcabd00df95d1028a66f71784b0b68f1178. Icepack regression testing bit-for-bit on cheyenne https://github.com/CICE-Consortium/Test-Results/wiki/icepack_by_hash_forks#0c573347b261eba1ab6a373273cc232a7feb1ee1
How much do the PR code changes differ from the unmodified code?
Does this PR create or have dependencies on CICE or any other models?
Does this PR add any new test cases?
Is the documentation being updated? ("Documentation" includes information on the wiki or in the .rst files from doc/source/, which are used to create the online technical docs at https://readthedocs.org/projects/cice-consortium-cice/.)
Please provide any additional information or relevant details below:
Use argcheck design
Eliminate local copies of optional data
Pass optional arguments down the calling tree
Some minor format cleanup