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 support for staggered atmospheric levels #364

Merged
merged 6 commits into from
May 28, 2021

Conversation

phil-blain
Copy link
Member

@phil-blain phil-blain commented May 26, 2021

PR checklist

  • Short (1 sentence) summary of your PR:
    Add support for staggered atmospheric levels
  • Developer(s):
    P. Blain based on code from F. Roy.
  • 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.
    All tests are bit for bit with master: https://github.com/CICE-Consortium/Test-Results/wiki/5fcfe7d103.daley.intel.21-05-26.201401.0
  • How much do the PR code changes differ from the unmodified code?
    • bit for bit
    • different at roundoff level
    • more substantial
  • Does this PR create or have dependencies on CICE or any other models?
  • Does this PR add any new test cases?
    • Yes
    • No
  • 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/.)
    • Yes
    • No, does the documentation need to be updated at a later time?
      • Yes
      • No
  • Please provide any additional information or relevant details below:
    In some applications, we might want the atmospheric input variables (wind, temperature and humidity) to be given at different vertical levels. For example, we might want to receive the winds at some level and the scalar variables (temperature and humidity) at another. This PR adds an optional argument zlvs to subroutine atmo_boundary_layer (and its callers), which corresponds to the vertical level at which the scalar variables are computed. The argument is optional so that so that higher-level drivers can optionally use the feature.

I also refactored the code a bit to make it more easily understandable.


This was implemented in our in-house versions of CICE4 and CICE5 and I'm porting it over to the Consortium as part of our project of updating our systems to CICE6.

The two functions 'psimhu' and 'psixhu' in icepack_atmo compute the
stability functions in the unstable case for momentum and scalars (heat
and water), respectively. They are both function of X := (1 - 16
\zeta)^(1/4) (see [1], section 8.1.1). In the code X is computed first
('xqq') and passed to 'psimhu' and 'psixhu'.

Add two new functions with more explicit names, 'psi_momentum_unstable'
and 'psi_scalar_unstable', that take \zeta ('hol') as argument,
compute X internally and return the evaluated stability function.

A subsequent commit will refactor the code to use them.

[1] B.G. Kauffman and W.G. Large. The CCSM coupler, version 5.0.1. 2002.
URL: https://github.com/CICE-Consortium/CICE/blob/master/doc/PDF/KL_NCAR2002.pdf.
Use the new functions 'psi_momentum_unstable' and 'psi_scalar_unstable'
introduced in the preceding commit to compute the stability function
evaluated at 'hol'. Remove duplicated computation  of 'xqq'.

Also remove the now unused functions 'psimhu' and 'psixhu'.
In a subsequent commit, we will support receiving the momentum and
scalar atmospheric variables at different levels. In order to minimize
code duplication, factor out the computation of the stability parameter
'hol' and the stability function 'psi[mx]h' in function
'compute_stability_parameter' and subroutine
'compute_stability_function'.

'compute_stability_function' also makes available the unit step function
evaluated at 'hol', 'stable', since it is used at the end of
'atmo_boundary_layer' to compute the diagnostic temperature and
humidity.
In some applications, we might want the atmospheric input variables
(wind, temperature and humidity) to be given at different vertical
levels. For example, we might want to receive the winds at some level
and the scalar variables (temperature and humidity) at another.

To support this use case, add an optional argument 'zlvs' to subroutine
'icepack_atm_boundary', and pass it down to 'atmo_boundary_layer' also
as an optional argument, so that existing applications do not have to be
changed if they do not want to use this feature.

The name 'zlvs' is chosen to mirror the existing variable 'zlvl', but
with the suffix 's' for 'scalars', mimicking the existing convention for
several variables in 'atmo_boundary_layer'.

In 'atmo_boundary_layer', add new local variables 'alzs' and 'hols' to
hold quantities computed at zlvs.  Also, for clarity, rename 'alz' to
'alzm' and 'hol' to 'holm', where the 'm' suffix stands for 'momentum',
again mimicking existing convention in the subroutine.

If 'zlvs' is not passed to 'atmo_boundary_layer', it is assumed that all
variables are given at the same level (zlvl), so in that case there is
no change in the results.
The previous commit added an optional 'zlvs' argument to
'icepack_atm_boundary' to allow atmospheric input variables to be given
at different vertical levels.

Also add 'zlvs' as an optional argument to 'icepack_step_therm1', to
make the functionality available via the Icepack interfaces.
Copy link
Contributor

@eclare108213 eclare108213 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 okay to me, just reading through it. Can you add a note about it in the text of the documentation, explaining how it works?

@phil-blain
Copy link
Member Author

@eclare108213 yes I'll do that.

@phil-blain
Copy link
Member Author

I've just pushed a new version of the last commit with some modifications to the Science guide. See the build here: https://cice-consortium-icepack--364.org.readthedocs.build/en/364/science_guide/sg_boundary_forcing.html#atmosphere

Copy link
Contributor

@apcraig apcraig left a comment

Choose a reason for hiding this comment

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

There may be two places where an optional argument is passed into a subroutine without checking if that argument was passed into the calling subroutine. This is one of the major issues with the current implementation of icepack. My recommendation has been to create a local variable, set it to a default if the optional variable is not passed, then pass that local variable into other subroutines. Something like

real (kind=dbl_kind) :: lzlvs

if (present(zlvs)) then
  lzlvs = zlvs
else
  lzlvs = zlvl
endif

call subroutine(..., zlvs=lzlvs, ....)

If there are better ways to handle this, I'd love to know! I don't think the "optional" attribute is carried with the argument as you try to pass it down the calling tree, but maybe there is a way to do this?

@@ -2539,7 +2541,7 @@ subroutine icepack_step_therm1(dt, ncat, nilyr, nslyr, &
Qa_iso=l_Qa_iso, &
Qref_iso=Qrefn_iso, &
uvel=uvel, vvel=vvel, &
Uref=Urefn)
Uref=Urefn, zlvs=zlvs)
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like passing zlvs here could be a problem if zlvs is not passed into icepack_step_therm1.

@@ -965,7 +969,7 @@ subroutine icepack_atm_boundary(sfctype, &
Qa_iso=l_Qa_iso, &
Qref_iso=l_Qref_iso, &
uvel=l_uvel, vvel=l_vvel, &
Uref=l_Uref)
Uref=l_Uref, zlvs=zlvs)
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like passing zlvs here could be a problem if zlvs is not passed into icepack_atm_boundary.

@phil-blain
Copy link
Member Author

Yes, I thought about that myself when writing the code and checked my copy of Modern Fortran Explained. It is said that the optional attribute is carried forward though the call stack. That is why I did not use local variables as you suggest...

Section 5.13 "Keyword and optional arguments" (p .89):

In such a case, an absent optional argument is also regarded as absent in the second-level subprogram. [...] Such absent arguments may be propagated through any number of calls, provided the dummy argument is optional each case

@apcraig
Copy link
Contributor

apcraig commented May 27, 2021

Interesting. I think we've run into problems before not checking optional arguments, but maybe I'm not remembering correct. (See for example Qa_iso in icepack_atmo.F90). If this is robust, that's going to be very helpful moving forward. Maybe Qa_iso creates different problems because it's an array?

@phil-blain
Copy link
Member Author

Maybe some compiler implementations you were using are not conforming... might be worth fetching this branch and running the tests suite on more machines ? It builds and runs fine on Intel and Gfortran...

@@ -143,6 +144,10 @@ respectively, given the ice velocity :math:`\vec{U}_i`:
\end{aligned}
:label: stars


Note that *atmo_boundary_layer* also accepts an optional argument, ``zlvs``, to support receiving scalar quantities from the atmospheric model (humidity and temperature)
at a different vertical level than the winds. In that case a separate stability :math:`\Upsilon_s` is computed using the same formula as above but substituting :math:`z_o` by :math:`z_{o,s}`.
Copy link
Contributor

Choose a reason for hiding this comment

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

The "staggered" terminology makes sense here in the way that you use it, but it would be helpful to just add (staggered) after at a different vertical level than the winds, to more directly connect the comment below with this one. Optional.

Copy link
Member Author

Choose a reason for hiding this comment

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

yes, good idea.

Copy link
Member Author

Choose a reason for hiding this comment

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

I've just pushed an updated commit that now reads

Note that atmo_boundary_layer also accepts an optional argument, zlvs, to support staggered atmospheric levels, i.e. receiving scalar quantities from the atmospheric model (humidity and temperature)at a different vertical level than the winds.

Copy link
Contributor

@eclare108213 eclare108213 left a comment

Choose a reason for hiding this comment

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

Was interfaces.include.orig committed intentionally? Looks like it's a personal copy.

@phil-blain
Copy link
Member Author

Oups. I did git add doc so it was automatically included... it's not a personal copy, it's generated by the gen_interfaces.sh script and not cleaned up at the end...

mv ${rstfile} ${rstfile}.orig

I'll re-push without it.

Add an index entry for 'zlvs' and mention it in the 'Atmopshere' section
of the science guide.
@apcraig
Copy link
Contributor

apcraig commented May 28, 2021

I ran full test suites of both Icepack and CICE with the staggered atmosphere levels and everything works fine. If we can leverage the fact that the optional attribute is carried thru the code for future developments, that is very helpful. There may be cases where we can't use it, but when we can, we should. Thanks @phil-blain.
https://github.com/CICE-Consortium/Test-Results/wiki/icepack_by_hash_forks#a3824f10e3510615067f91e6c8ee97dddb9c2b24
https://github.com/CICE-Consortium/Test-Results/wiki/cice_by_hash_forks#d71069b2bc51ab5d4fb32ca22a35d453ebedd377

@apcraig apcraig merged commit 37f2a17 into CICE-Consortium:master May 28, 2021
@phil-blain phil-blain deleted the atmo-staggered-levels branch May 28, 2021 18:08
phil-blain added a commit to phil-blain/Icepack that referenced this pull request Feb 6, 2024
When we compute the diagnostic temperature and humidity (at zTrf) at the
end of icepack_atmo::atmo_boundary_layer, we shift the stability
parameter (hols) by multiplying it by zTrf/zlvl, but this is incorrect
when staggered atmospheric levels are used, as zlvl is the atmospheric
level height for momentum, not for scalars (temperature and humidity).

This is a bug introduced in 37f2a17 (Add support for staggered
atmospheric levels (CICE-Consortium#364), 2021-05-28) but only changes diagnostics
if staggered atmospheric levels are used, i.e. if zlvs /= zlvl.

Correct that by dividing by zlvs, the atmospheric level height for
scalars, when it is present.

While at it, adjust the indentation of the description comment for
'zlvs', so it is aligned with the other variables.
phil-blain added a commit to phil-blain/Icepack that referenced this pull request Feb 6, 2024
In 37f2a17 (Add support for staggered atmospheric levels (CICE-Consortium#364),
2021-05-28), we introduced the subroutine compute_stability_function,
which computes the stability function during the iteration in
'icepack_amto::atmo_boundary_layer'. This subroutine also returns the
unit step function 'stable' at 'hol', since it is used at the end of the
computation to compute the diagnostic temperature and humidity. Note
that we overwrite 'stable' in the second call to
compute_stability_function, but this is OK since we call it first for
momentum and then for scalars, and it is the value for scalars that we
want to use later for diagnostic temperature and humdity.

In a following commit we will want to compute the diagnostic _velocity_
in a different way than what is done now, and we will need the unit step
function computed at the momentum level (which is currently
overwritten). In preparation for that change, add a new variable
'stablem' for the unit step function at the momentum level, and rename
the existing 'stable' variable to 'stables' (for scalars). Adjust the
computation of 'psix2' accordingly.
phil-blain added a commit to phil-blain/Icepack that referenced this pull request Feb 7, 2024
When we compute the diagnostic temperature and humidity (at zTrf) at the
end of icepack_atmo::atmo_boundary_layer, we shift the stability
parameter (hols) by multiplying it by zTrf/zlvl, but this is incorrect
when staggered atmospheric levels are used, as zlvl is the atmospheric
level height for momentum, not for scalars (temperature and humidity).

This is a bug introduced in 37f2a17 (Add support for staggered
atmospheric levels (CICE-Consortium#364), 2021-05-28) but only changes diagnostics
if staggered atmospheric levels are used, i.e. if zlvs /= zlvl.

Correct that by dividing by zlvs, the atmospheric level height for
scalars, when it is present.

While at it, adjust the indentation of the description comment for
'zlvs', so it is aligned with the other variables.
phil-blain added a commit to phil-blain/Icepack that referenced this pull request Feb 7, 2024
In 37f2a17 (Add support for staggered atmospheric levels (CICE-Consortium#364),
2021-05-28), we introduced the subroutine compute_stability_function,
which computes the stability function during the iteration in
'icepack_amto::atmo_boundary_layer'. This subroutine also returns the
unit step function 'stable' at 'hol', since it is used at the end of the
computation to compute the diagnostic temperature and humidity. Note
that we overwrite 'stable' in the second call to
compute_stability_function, but this is OK since we call it first for
momentum and then for scalars, and it is the value for scalars that we
want to use later for diagnostic temperature and humdity.

In a following commit we will want to compute the diagnostic _velocity_
in a different way than what is done now, and we will need the unit step
function computed at the momentum level (which is currently
overwritten). In preparation for that change, add a new variable
'stablem' for the unit step function at the momentum level, and rename
the existing 'stable' variable to 'stables' (for scalars). Adjust the
computation of 'psix2' accordingly.
phil-blain added a commit to phil-blain/Icepack that referenced this pull request Feb 12, 2024
When we compute the diagnostic temperature and humidity (at zTrf) at the
end of icepack_atmo::atmo_boundary_layer, we shift the stability
parameter (hols) by multiplying it by zTrf/zlvl, but this is incorrect
when staggered atmospheric levels are used, as zlvl is the atmospheric
level height for momentum, not for scalars (temperature and humidity).

This is a bug introduced in 37f2a17 (Add support for staggered
atmospheric levels (CICE-Consortium#364), 2021-05-28) but only changes diagnostics
if staggered atmospheric levels are used, i.e. if zlvs /= zlvl.

Correct that by dividing by zlvs, the atmospheric level height for
scalars, when it is present.

While at it, adjust the indentation of the description comment for
'zlvs', so it is aligned with the other variables.
phil-blain added a commit to phil-blain/Icepack that referenced this pull request Feb 12, 2024
In 37f2a17 (Add support for staggered atmospheric levels (CICE-Consortium#364),
2021-05-28), we introduced the subroutine compute_stability_function,
which computes the stability function during the iteration in
'icepack_amto::atmo_boundary_layer'. This subroutine also returns the
unit step function 'stable' at 'hol', since it is used at the end of the
computation to compute the diagnostic temperature and humidity. Note
that we overwrite 'stable' in the second call to
compute_stability_function, but this is OK since we call it first for
momentum and then for scalars, and it is the value for scalars that we
want to use later for diagnostic temperature and humdity.

In a following commit we will want to compute the diagnostic _velocity_
in a different way than what is done now, and we will need the unit step
function computed at the momentum level (which is currently
overwritten). In preparation for that change, add a new variable
'stablem' for the unit step function at the momentum level, and rename
the existing 'stable' variable to 'stables' (for scalars). Adjust the
computation of 'psix2' accordingly.
phil-blain added a commit to phil-blain/Icepack that referenced this pull request Feb 12, 2024
When we compute the diagnostic temperature and humidity (at zTrf) at the
end of icepack_atmo::atmo_boundary_layer, we shift the stability
parameter (hols) by multiplying it by zTrf/zlvl, but this is incorrect
when staggered atmospheric levels are used, as zlvl is the atmospheric
level height for momentum, not for scalars (temperature and humidity).

This is a bug introduced in 37f2a17 (Add support for staggered
atmospheric levels (CICE-Consortium#364), 2021-05-28) but only changes diagnostics
if staggered atmospheric levels are used, i.e. if zlvs /= zlvl.

Correct that by dividing by zlvs, the atmospheric level height for
scalars, when it is present.

While at it, adjust the indentation of the description comment for
'zlvs', so it is aligned with the other variables.
phil-blain added a commit to phil-blain/Icepack that referenced this pull request Feb 12, 2024
In 37f2a17 (Add support for staggered atmospheric levels (CICE-Consortium#364),
2021-05-28), we introduced the subroutine compute_stability_function,
which computes the stability function during the iteration in
'icepack_amto::atmo_boundary_layer'. This subroutine also returns the
unit step function 'stable' at 'hol', since it is used at the end of the
computation to compute the diagnostic temperature and humidity. Note
that we overwrite 'stable' in the second call to
compute_stability_function, but this is OK since we call it first for
momentum and then for scalars, and it is the value for scalars that we
want to use later for diagnostic temperature and humdity.

In a following commit we will want to compute the diagnostic _velocity_
in a different way than what is done now, and we will need the unit step
function computed at the momentum level (which is currently
overwritten). In preparation for that change, add a new variable
'stablem' for the unit step function at the momentum level, and rename
the existing 'stable' variable to 'stables' (for scalars). Adjust the
computation of 'psix2' accordingly.
phil-blain added a commit to phil-blain/Icepack that referenced this pull request Feb 12, 2024
In 37f2a17 (Add support for staggered atmospheric levels (CICE-Consortium#364),
2021-05-28), we introduced the subroutine compute_stability_function,
which computes the stability function during the iteration in
'icepack_amto::atmo_boundary_layer'. This subroutine also returns the
unit step function 'stable' at 'hol', since it is used at the end of the
computation to compute the diagnostic temperature and humidity. Note
that we overwrite 'stable' in the second call to
compute_stability_function, but this is OK since we call it first for
momentum and then for scalars, and it is the value for scalars that we
want to use later for diagnostic temperature and humdity.

In a following commit we will want to compute the diagnostic _velocity_
in a different way than what is done now, and we will need the unit step
function computed at the momentum level (which is currently
overwritten). In preparation for that change, add a new variable
'stablem' for the unit step function at the momentum level, and rename
the existing 'stable' variable to 'stables' (for scalars). Adjust the
computation of 'psix2' accordingly.
phil-blain added a commit to phil-blain/Icepack that referenced this pull request Feb 12, 2024
When we compute the diagnostic temperature and humidity (at zTrf) at the
end of icepack_atmo::atmo_boundary_layer, we shift the stability
parameter (hols) by multiplying it by zTrf/zlvl, but this is incorrect
when staggered atmospheric levels are used, as zlvl is the atmospheric
level height for momentum, not for scalars (temperature and humidity).

This is a bug introduced in 37f2a17 (Add support for staggered
atmospheric levels (CICE-Consortium#364), 2021-05-28) but only changes diagnostics
if staggered atmospheric levels are used, i.e. if zlvs /= zlvl.

Correct that by dividing by zlvs, the atmospheric level height for
scalars, when it is present.

While at it, adjust the indentation of the description comment for
'zlvs', so it is aligned with the other variables.
phil-blain added a commit to phil-blain/Icepack that referenced this pull request Feb 12, 2024
In 37f2a17 (Add support for staggered atmospheric levels (CICE-Consortium#364),
2021-05-28), we introduced the subroutine compute_stability_function,
which computes the stability function during the iteration in
'icepack_amto::atmo_boundary_layer'. This subroutine also returns the
unit step function 'stable' at 'hol', since it is used at the end of the
computation to compute the diagnostic temperature and humidity. Note
that we overwrite 'stable' in the second call to
compute_stability_function, but this is OK since we call it first for
momentum and then for scalars, and it is the value for scalars that we
want to use later for diagnostic temperature and humdity.

In a following commit we will want to compute the diagnostic _velocity_
in a different way than what is done now, and we will need the unit step
function computed at the momentum level (which is currently
overwritten). In preparation for that change, add a new variable
'stablem' for the unit step function at the momentum level, and rename
the existing 'stable' variable to 'stables' (for scalars). Adjust the
computation of 'psix2' accordingly.
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.

3 participants