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

Implementation of GL90 vertical viscosity parameterization #23

Closed
wants to merge 38 commits into from

Conversation

NoraLoose
Copy link
Member

The parameterization "GL90''

This PR implements a vertical viscosity parameterization a la Greatbatch and Lamb (1990), Ferreira & Marshall (2006) and Zhao & Vallis (2008), hereafter referred to as the GL90 vertical viscosity parameterization. This vertical viscosity scheme redistributes momentum in the vertical, and is the equivalent of the Gent & McWilliams (1990) parameterization, but in a TWA (thickness-weighted averaged) set of equations. The vertical viscosity coefficient nu is computed from kappa_GM
via thermal wind balance, and the following relation:

nu = kappa_GM * f^2 / N^2,

where f is the Coriolis parameter, and N^2 is the buoyancy frequency. kappa_GM can vary horizontally and vertically, but for now the implementation assumes horizontally and vertically constant kappa_GM. The vertical viscosity del_z ( nu del_z u) is applied to the momentum equation with stress-free boundary conditions at the top and bottom.

Using GL90 with NeverWorld2: first results

I have run NeverWorld2 0.5 degree with GL90 switched on (and GM90 switched off). This is the only switch that has to be done in order to run adiabatic NeverWorld2 in the TWA equations. The implementation is working as expected:

  • Figure 1 and 2 below show that the viscosity (diagnosed online via Kv_u, Kv_v) is enhanced where stratification is weak (because nu ~ 1/N^2), and zero at the equator (because nu ~ f^2).
  • The kinetic energy budget closes, and behaves as expected (see Figure 3 and 4 below). That is, when substituting GM90 by GL90, the main KE sink term is not conversion to PE anymore; instead, the main sink is the GL90 work which acts directly on the KE budget (consistent with the Bleck energy cycle).

Next steps

I want to work on a few more things before we can consider merging this. I am hoping I can get input from @Hallberg-NOAA on the following questions / roadmap:

  • KE budget diagnostics: I would like to implement a diagnostic for the GL_work (similar to the GM_work), i.e., the energetic effect of GL90 on the KE budget. In the plot below, the blue line is the difference KE_visc - KE_stress, and includes both the GL_work and the energetic effects of bottom drag and vertical viscosity not associated with GL90 (e.g., through background viscosity or enhanced viscosity in the mixed layer). Diagnosing GL_work would require a new diagnostic in MOM_vert_friction alongside with d[uv]_dt_visc and d[uv]_dt_str. I think to do this, we have to compute the coupling coefficients a_u, a_v in vertvisc_coef separately for the Kv_gl90_[uv] contributions. Would you agree?
  • Code efficiency & structure: I am computing the GL90 viscosity as part of a new subroutine in MOM_vert_friction. This subroutine is hacked together choosing the path of least resistance. For example, I am calling subroutines find_eta and calc_isoneutral_slopes to get at N^2. I'm sure this can be done more efficiently. Ultimately, we probably want to move the whole GL90 routine into its own module, because it will grow as we allow kappa_GM to vary vertically and horizontally. Thoughts?

@Hallberg-NOAA, or other people interested, would you have time for a meeting to discuss the code questions above? Thanks!

@NoraLoose
Copy link
Member Author

NoraLoose commented Mar 24, 2022

Total vertical viscosity along 3 zonal sections, diagnosed online (1) using GM with kappa_GM = 1000 m^2/s (first row) and (2) using GL with kappa_GM = 1000 m^2 (second row). When GL is switched on, the vertical viscosity is enhanced by a few orders of magnitudes, especially where stratification is weak (in the deep ocean)
viscosity_zonal_section

@NoraLoose
Copy link
Member Author

As previous figure, but now vertical viscosity is shown along 3 meridional sections. These figures emphasize how viscosity goes to zero as the equator is approached.
viscosity_meridional_section

@NoraLoose
Copy link
Member Author

NoraLoose commented Mar 24, 2022

KE budget using (a) GM with kappa_GM = 1000m^2/s, (b) GM with kappa_GM = 2000m^2/s, (c) GL with kappa_GL = 1000m^2/s, (b) GL with kappa_GM = 2000m^2/s.

KE_budget_0 5degree_parameterized2

  • In the GM framework (a, b), KE gets sent to PE (red line), from where it can be taken out by GM;
  • In the GL framework (c, d), KE gets taken out by vertical viscosity (blue line); this "GL_work" acts directly on the KE reservoir and parameterizes the effect of baroclinic instability in the TWA framework. Conversion to PE (red line) integrates to ~zero over the domain.

@NoraLoose
Copy link
Member Author

Final figure: The domain integral of the previous figure, which just underlines the previous point.
KE_budget_bars_0 5degree_parameterized

@NoraLoose
Copy link
Member Author

NoraLoose commented Mar 24, 2022

@adcroft
Copy link

adcroft commented Mar 25, 2022

It is remarkable how similar the solutions are between the two schemes.

I agree that making a new module makes sense (eventually). In the meantime, the efficiency issue could be addressed if we modularized (broke apart) calc_isoneutral_slopes() so that you can access N2_u and N2_v more readily.

Yes, to diagnose the conversion we need to keep a copy of the GL viscous coupling coefficients.

@StephenGriffies
Copy link

@adcroft "It is remarkable how similar the solutions are between the two schemes." I did not see any figures with fields to show the solutions are similar. The energetics quite distinct. Did I miss something?

@adcroft
Copy link

adcroft commented Mar 25, 2022

I did not see any figures with fields to show the solutions are similar.

@NoraLoose posted 12 panels showing the hydrography. The only major differences I see are near the surface,

@StephenGriffies
Copy link

I only see viscosity and energy line plots. Must be working on a different planet.

@StephenGriffies
Copy link

Anyhow, the similarities are expected.

@adcroft
Copy link

adcroft commented Mar 25, 2022

I only see viscosity and energy line plots. Must be working on a different planet.

View the PR on GitHub. #23 (comment)

@NoraLoose
Copy link
Member Author

@adcroft and @StephenGriffies: I think you are looking at the same plots. The plots are indeed showing viscosity, but Alistair may be referring to the interface height positions (shown by the black lines) as "hydrography".

@NoraLoose
Copy link
Member Author

And yes, so far I haven't seen big differences in the solutions between the two schemes, except for the energetics. I have been only looking at 500-day averages and the 0.5 degree simulation, though. (That's what the above plots are for.)

@NoraLoose
Copy link
Member Author

In the meantime, the efficiency issue could be addressed if we modularized (broke apart) calc_isoneutral_slopes() so that you can access N2_u and N2_v more readily.

@adcroft I agree, this would be a good thing to do. I searched around in the MOM6 code to see how computation of N2 is handled in other places. I found a very simple solution (4 lines of code instead of calling 2 subroutines):

Hdn = 2.*h(i,j,k)*h(i,j,k-1) / (h(i,j,k) + h(i,j,k-1) + h_neglect)
Hup = 2.*h(i+1,j,k)*h(i+1,j,k-1) / (h(i+1,j,k) + h(i+1,j,k-1) + h_neglect)
H_geom = sqrt(Hdn*Hup)
N2 = GV%g_prime(k)*US%L_to_Z**2 / (GV%H_to_Z * max(Hdn,Hup,one_meter))

This solution would work for NeverWorld2 but not for more complex (non-adiabatic) MOM6 setups, correct?

@adcroft
Copy link

adcroft commented Mar 25, 2022

Correct: that fn does not give N^2 if density is variable along layers or different from that implied by g' . It also has a "fix" to handle vanished layers that might not be appropriate for this application. In your case you want 1/N^2 so it might be better to think of it as h/g' in which case vanished layers are not the problem but instead a vanishing density difference (g') leads to large numbers. We should get Bob in a call to discuss options (as you asked higher up).

@NoraLoose
Copy link
Member Author

Good point about the peculiarities of computing 1/N^2 (rather than N^2). This implies that we should probably write a new subroutine for this particular application (rather than calling subroutines that are specialized to compute N^2, not 1/N^2).

@iangrooms
Copy link
Member

The Ferrari/Griffies/Nurser/Vallis approach could potentially be used here both to set the stress to 0 at the top and bottom boundaries, and also to deal with 'interpolating' through regions of low or negative N^2. Specifically, the vertical stress in this parameterization is

tau = (kappa f^2/N^2)du/dz

(possibly up to a minus sign - I can't recall the convention for the definition of stress). If you instead define tau to be the solution of

c^2 d^2tau/dz^2 - N^2 tau = -kappa f^2du/dz

and truncate negative values of N^2, then you get a stress that has the desired boundary conditions and also handles small or negative N^2 gracefully. It also allows re-purposing the existing FGNV10 code from GM to GL. I think it would require re-tooling the implicit vertical viscosity solver, but it might end up just requiring 2 tridiagonal solves instead of 1.

@MFJansen
Copy link

I think it would be good to take a step back to the SSW theory to think about what exactly this "1/N^2" term here should be, rather than taking the z-coordinate expression and then trying to approximate it in SSW.

I also agree with Ian about FGNV being potentially useful here - in fact this issue of infinite viscosity for vanishing stratification is basically the same as the issue of infinite streamfunction for vanishing stratification in GM, so all the things that people have been doing to deal with that should apply.

@adcroft
Copy link

adcroft commented Mar 25, 2022

FGNV is an interesting idea but the stress is already being solved implicitly-in-time leading to an elliptic equation. This would be a second equation for stress but I think the issue is we need to calculate a bounded viscosity.

@MFJansen
Copy link

MFJansen commented Mar 25, 2022

Following up on my point above, if I’m getting this right, I think we ultimately want the form stress at each interface to be given by fK_GM\grad\eta. Using Margules, this is f^2/g’ K_GM\Delta u_g, with \Delta u_g the (geostrophic) velocity contrast at that interface (and to get the whole thing to look like a regular vertical viscosity we need to approximate u_g as u). So following this logic, 1/N^2 basically just gets dz/g' where the dz should just cancel the dz that appears in the finite difference to get the velocity shear, no?

@MFJansen
Copy link

I'm also going to repeat a suggestion I made in the chat during the call: Would it be worth trying to just implement the form stress as fK_GM\grad\eta, which in fact can be written as f \Psi_GM, with Psi_GM computed as before (thus allowing us to reuse all that code that already exists - including tapering schemes etc.)?

- don't let the GL90 coupling coefficient feel BBL anymore
- effectively use hvel (which close to bottom has upwind biased thickness)
  to avoid spurious effects close to almost vanished layers and topography
- GL90 coupling coefficient is now computed more computationally efficient:
  only at one j-index at a time, consistent with other routines
- remove dependency on tv, which may have to re-added in the future for
  computing N^2. but not needed in SSW because here N^2 = g'/h.
@NoraLoose
Copy link
Member Author

Hi @Hallberg-NOAA, @adcroft, @MFJansen, @iangrooms, @sdbachman, @gustavo-marques et al.,

I have some issues with the GL90 vertical viscosity scheme in grid cells that are horizontally adjacent to vanished layers. To illustrate the problem, the following figure shows two meridional sections (sketched in green in subpanel on the left), close to the continental slope. Shown is the 1 degree NW2 simulation - so the two sections are for neighboring grid cells.

First row: Section along 3E, where the lowermost layers are all vanished because they are riding over the topographic slope.
Second row: Section along 4E, where the same layers have thickness O(100m). As you can see, these layers have large spurious zonal velocities (left and middle panel).

GLvelocities

The following sketch may be helpful to understand the problem better:

June 002

The coupling coefficients a_GL that go into the implicit vertical viscosity scheme live on interfaces and velocity points. (I am setting these coupling coefficients in the subroutine find_coupling_coef_gl90, which is newly added as part of this PR.)
In SSW mode, they are (on paper) given by

a_GL(I,K) = kappa f^2 / g'(K)

But we probably want these coupling coefficients to not be active when we are adjacent to vanished layers. So I have tried to multiply them by h / (h + epsilon) (green term in sketch), where h is an upwind-biased thickness estimate if you are close to topography and next to vanished layers. So we should have h~0 as well as (green term) ~ 0 for the case illustrated above. However, this did not eliminate the problem.

Any recommendations for what to try next? Thanks for your help!

@adcroft
Copy link

adcroft commented Jun 2, 2022

We need to figure out if this is coming from the vertical grid used for the viscosity or the viscosity itself. OOI, what happens if you set KV to a large constant value of order the GL value? Is HARMONIC_VISC true of false (which affects the other viscosities)? Perhaps time to meet about this...

@NoraLoose
Copy link
Member Author

@adcroft, that’s a good point, thanks! HARMONIC_VISC = False and KV = 1E-4 m2 s-1 for the simulations shown above.

There doesn’t seem to be a problem if I use (first column) a large KV = 1 m2 s-1, HARMONIC_VISC = False or (second column) GM instead of GL, with KV = 1E-4 m2 s-1, HARMONIC_VISC = False. In this figure, the colorbar range is [-0.01, 0.01] (compared to [-0.1, 0.1] above) to make sure we are not missing any spurious velocities. But it seems there aren't any!

largeKV

So the problem must be the a_cpl_GL90 coefficient itself. Here are some hints: The problem

  • does not arise if I set
          a_cpl_gl90(I,K) = 2.0 * f2 * CS%alpha_gl90 / (hvel(I,k) + hvel(I,k-1) + h_neglect)

which corresponds to depth-independent nu_GL (see third column in first figure);

  • does arise if I set
          a_cpl_gl90(I,K) = f2 * CS%kappa_gl90 / GV%g_prime(K)

or

          a_cpl_gl90(I,K) = f2 * CS%kappa_gl90 / GV%g_prime(K) * (hvel(I,k) + hvel(I,k-1)) / (hvel(I,k) + hvel(I,k-1) + h_neglect)

@NoraLoose
Copy link
Member Author

NoraLoose commented Jun 7, 2022

I have looked at some more diagnostics to get to the bottom of the problem.

This figure compares the vertical profile of Hu_visc for GM (green) vs. GL (pink) in a 1 degree simulation. Hu_visc is the thickness at u-points that is used in the vertical viscosity scheme (essentially hvel in the above schematic). The 4 columns show the vertical profiles as ones moves grid-point-wise across the continental shelf: 2E, 3E, 4E, 5E.

The second row is a copy of the first row, but each panel zooms into the leftmost part of the panel above (the first 10m). What is striking is that GL allows layers of Hu_visc = O(1m) (circled in black), while with GM the vertical transition from vanished to non-vanished layers seems to be much sharper: from Hu_visc = 0m to Hu_visc = O(100m) for the layer above.

GLdiagnostics 002

For reference, here are the coupling coefficients used in the vertical viscosity scheme, diagnosed online for the same time step as the figure above. Total coupling coefficient au_visc (first row) and the GL90 coupling coefficient au_gl90_visc (second row). Note that the scale of the x-axis varies by orders of magnitude across subpanels.

GLdiagnostics 001

The GL90 coupling coefficient does not do anything crazy, but it is always > 0. So maybe it somehow interferes with the peculiar vertical shape of Hu_visc?

cc @adcroft @Hallberg-NOAA

@NoraLoose
Copy link
Member Author

Closing this PR because this code has been merged into the NOAA-GFDL MOM6 branch via NOAA-GFDL#268 and
NOAA-GFDL#293.

@NoraLoose NoraLoose closed this Jan 9, 2023
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.

7 participants