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

Frequency-dependent internal wave drag #722

Open
wants to merge 5 commits into
base: dev/gfdl
Choose a base branch
from

Conversation

c2xu
Copy link

@c2xu c2xu commented Sep 12, 2024

Utilizing streaming bandpass filters, the linear wave drag can now be applied to the M2 and K1 velocities independently, without affecting the broadband barotropic velocity fields. This implementation would be particularly useful (and perhaps necessary) for correctly representing tides in climate simulations, because if the linear drag is applied to the broadband barotropic velocity, the low-frequency, non-tidal motions would also be damped.

Utilizing streaming bandpass filters, the linear wave drag can now be
applied to the M2 and K1 velocities independently, without affecting
the broadband barotropic velocity fields.
Simplified the implementation by allowing both linear wave drag and
frequency-dependent drag to be turned on at the same time.
@Hallberg-NOAA Hallberg-NOAA added enhancement New feature or request Parameter change Input parameter changes (addition, removal, or description) labels Sep 16, 2024
@c2xu c2xu marked this pull request as draft September 16, 2024 17:10
@c2xu c2xu force-pushed the c2xu/linear_freq_drag branch 2 times, most recently from 8fbeaf3 to 398b79c Compare September 16, 2024 17:26
Minor update for performance optimization.
@c2xu
Copy link
Author

c2xu commented Sep 20, 2024

I tested the new implementation and after a small bug fix, the results are identical as before.

@c2xu c2xu marked this pull request as ready for review September 20, 2024 23:55
@herrwang0
Copy link

It looks to me the newly-added Drag_[uv] forcing term does not change for each baroclinic time step. And as @Hallberg-NOAA suggested and the changes adopted since, it makes more sense to add it to BT_force_[uv] (vertical sum of baroclinic forcings).

Following the same logic, I kind of wanted to open an discussion on whether BT solver would be the best place to house the calculation of Drag_[uv]. In my opinion, here are the pros and cons for having it in BT solver.

  • Pros
  1. The filter as it stands is based on barotropic velocities and we can avoid repeating calculations of barotropic velocities.
  2. Drag_[uv] is essentially a 2D force on the whole column, so it is a barotropic force.
  • Cons
  1. The term is essentially updated every baroclinic time step. So there is no difference between doing the calculation inside and outside of BT solver. For BT solver, the term is no different from any other vertically-summed baroclinic forcing terms. I always think (and I could be wrong) BT solver should be reserved for calculating forcings that are time-varying for each BT step.
  2. If you look from a momentum budget perspective, the journey through BT solver makes Drag_[uv] embedded in [uv]_accel_bt, along with time-varying barotropic forcings, which will be diagnostics "[uv]_BT_accel". This seems counterintuitive and confusing to me.
  3. I wonder if it makes it difficult for potentially expansion of the functionality in the future. What if we want to apply it to non-barotropic velocity (say, bottom velocity)?

@c2xu
Copy link
Author

c2xu commented Sep 22, 2024

It looks to me the newly-added Drag_[uv] forcing term does not change for each baroclinic time step. And as @Hallberg-NOAA suggested and the changes adopted since, it makes more sense to add it to BT_force_[uv] (vertical sum of baroclinic forcings).

Following the same logic, I kind of wanted to open an discussion on whether BT solver would be the best place to house the calculation of Drag_[uv]. In my opinion, here are the pros and cons for having it in BT solver.

  • Pros
  1. The filter as it stands is based on barotropic velocities and we can avoid repeating calculations of barotropic velocities.
  2. Drag_[uv] is essentially a 2D force on the whole column, so it is a barotropic force.
  • Cons
  1. The term is essentially updated every baroclinic time step. So there is no difference between doing the calculation inside and outside of BT solver. For BT solver, the term is no different from any other vertically-summed baroclinic forcing terms. I always think (and I could be wrong) BT solver should be reserved for calculating forcings that are time-varying for each BT step.
  2. If you look from a momentum budget perspective, the journey through BT solver makes Drag_[uv] embedded in [uv]_accel_bt, along with time-varying barotropic forcings, which will be diagnostics "[uv]_BT_accel". This seems counterintuitive and confusing to me.
  3. I wonder if it makes it difficult for potentially expansion of the functionality in the future. What if we want to apply it to non-barotropic velocity (say, bottom velocity)?

Thanks for the comments, but I think ideally, for better accuracy, the tidal velocities [uv]m2 and [uv]k1, and hence Drag_[uv], should be calculated for each barotropic time step instead of baroclinic time step, though this seems to significantly increase the computational cost (about 20%-30% increase of computation time for one-layer, tide only simulations, though this could change depending on the configuration). There is also the complexity related to the prediction steps versus correction steps when calculating [uv]m2 and [uv]k1 using the current streaming filter module.

For my own configuration (one-layer, tide only model), the current implementation seems to work fine. But we should definitely keep this conversation open, as we might want to modify the implementation depending on the application. For example, in 3D models, we might want to apply the drag to certain layers instead of the barotropic velocity. And in simulations where the baroclinic time step is large, then the drag should be time-varying for each BT step.

Bug fix for memory allocation of uninitialized tidal velocities.
if (len_trim(m2_drag_u) > 0 .and. len_trim(m2_drag_v) > 0) then
call MOM_read_data(wave_drag_file, m2_drag_u, CS%lin_drag_um2, G%Domain, &
position=EAST_FACE, scale=m2_drag_scale*GV%m_to_H*US%T_to_s)
call pass_var(CS%lin_drag_um2, G%Domain)
Copy link
Member

Choose a reason for hiding this comment

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

Doing a separate pass_var for lin_drag_um2 and lin_drag_vm2 will result in fields that do not rotate properly and will be incorrect at a norther tripolar fold. Moreover, as these variables are at the u- and v-points, it is incorrect to use pass_var calls without a flag to indicate this, as that routine assumes by default that these variables are at the h-points. The correct thing to do here would be to replace the two pass_var() calls at lines 5171 and 5175 with a single call to pass_vector(m2_drag_u, m2_drag_v, G%domain, direction=To_All+SCALAR_PAIR). The scalar pair here is because these are non-negative magnitudes and not components of a vector.

Similar changes should also be made to the pass_var() calls on lines 5197 and 5201 in this PR, and also to the calls on lines 5131 and 5135 that were introduced with PR #703. There is no reason to add a flag to recover the previous answers, because they could not pass the rotational symmetry testing and hence are demonstrably wrong.

Copy link
Author

Choose a reason for hiding this comment

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

Thanks for the explanation. This has been corrected.

Copy link
Member

@Hallberg-NOAA Hallberg-NOAA left a comment

Choose a reason for hiding this comment

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

Most of the issues with the previous version of this PR have been addressed, but in re-examining the code, I believe that there is a problem with the separate pass_var() calls for the u- and v- components of a staggered scalar field that appear in 3 places that should be corrected by replacing them with a call to pass_vector() before this can be merged into the dev/gfdl branch of MOM6.

Bug fix related to pass_vector()
@awallcraft
Copy link

The streaming filter time advances a set of coupled ODEs, so its prognostic variables need to be in the restart file. This would likely be a separate pull request against MOM_streaming_filter.F90, but the restart capability needs to be in place before this request is merged. Look for register_restart_field to see what is needed,
a 2-D example is in MOM_mixed_layer_restrat.F90.

It would be useful to have diagnostic output of um2, vm2, uk1 and vk1. So far as I can tell, these would be like the existing id_ubt_st diagnostic. Similarly Drag_u and Drag_v diagnostics would be like id_ubtforce.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request Parameter change Input parameter changes (addition, removal, or description)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants