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 KPP nonlocal term to passive tracers #202

Merged
merged 35 commits into from
Mar 9, 2022

Conversation

mnlevy1981
Copy link
Collaborator

When running with CS%useKPP = .true., the new function
call_tracer_KPP_NonLocalTransport() controls whether each tracer module applies
the KPP nonlocal term to its tracers. This has been implemented in the CFC
tracer module as a proof of concept, but has not been extended to other modules
yet.

For CFCs, there is a new parameter CFC_APPLY_NONLOCAL_TRANSPORT that, when true, applies
the nonlocal term to the CFC tracers (akin to APPLY_NONLOCAL_TRANSPORT and T & S)

When running with CS%useKPP = .true., the new function
call_tracer_KPP_NonLocalTransport() controls whether each tracer module applies
the KPP nonlocal term to its tracers. This has been implemented in the CFC
tracer module as a proof of concept, but has not been extended to other modules
yet.
@mnlevy1981
Copy link
Collaborator Author

A couple open questions:

  1. Is this implementation the correct approach?
  2. Should the default for CFC_APPLY_NONLOCAL_TRANSPORT be True? (It is False in the first commit in case backwards compatibility is necessary, although I suspect we want it to be True in CESM; I can override it in a MOM_interface PR if it should be False here)

Once the general approach is approved, I am happy to extend this to other tracer modules.

Also, it looks like I don't have permission to add reviewers to this PR... but I would suggest including some of the GFDL developers to help answer the above questions.

This commit should pass the doxygen CI test
@codecov-commenter
Copy link

codecov-commenter commented Nov 30, 2021

Codecov Report

Merging #202 (c3cbdf7) into dev/ncar (8106f48) will increase coverage by 0.00%.
The diff coverage is 6.97%.

❗ Current head c3cbdf7 differs from pull request most recent head e3d278e. Consider uploading reports for the commit e3d278e to get more accurate results

Impacted file tree graph

@@            Coverage Diff            @@
##           dev/ncar     #202   +/-   ##
=========================================
  Coverage     28.87%   28.87%           
=========================================
  Files           242      243    +1     
  Lines         71863    71875   +12     
=========================================
+ Hits          20749    20756    +7     
- Misses        51114    51119    +5     
Impacted Files Coverage Δ
src/core/MOM_forcing_type.F90 43.06% <ø> (ø)
src/core/MOM_variables.F90 28.57% <ø> (ø)
src/parameterizations/vertical/MOM_CVMix_KPP.F90 1.04% <0.00%> (+0.04%) ⬆️
src/tracer/MOM_CFC_cap.F90 18.18% <0.00%> (-1.53%) ⬇️
src/tracer/MOM_tracer_flow_control.F90 51.49% <0.00%> (-0.39%) ⬇️
src/tracer/MOM_tracer_types.F90 0.00% <0.00%> (ø)
src/tracer/pseudo_salt_tracer.F90 0.00% <0.00%> (ø)
...parameterizations/vertical/MOM_diabatic_driver.F90 38.94% <7.69%> (+0.13%) ⬆️
src/tracer/MOM_tracer_registry.F90 61.12% <31.57%> (-1.90%) ⬇️
src/core/MOM.F90 58.22% <50.00%> (+0.02%) ⬆️
... and 3 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 8106f48...e3d278e. Read the comment docs.

enddo

! Update tracer due to non-local redistribution of surface flux
if (applyNonLocalTrans) then
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is it desirable to call KPP_NonLocalTransport_passive_tracers when applyNonLocalTrans = False?
If yes, perhaps dtracer should only be calculated if applyNonLocalTrans = True or its diagnostic has been requested. If not, it would make more sense if this condition was outside of KPP_NonLocalTransport_passive_tracers.
The same comment applies for KPP_NonLocalTransport_temp and KPP_NonLocalTransport_saln.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The real issue is that I haven't plumbed in any diagnostics yet - for KPP_NonLocalTransport_temp and KPP_NonLocalTransport_saln, if applyNonLocalTrans is false then you still compute the terms and post the data, you just don't add the terms to the tracer quantities themselves... but when I first started working on this branch I got a little stuck trying to figure out how to include diagnostics and then I didn't come back to that before opening this PR

KPP_NonLocalTransport_passive_tracers() now posts surface flux and the tendency
due to the KPP nonlocal term if those diagnostics are requested in output.
There is probably a better way to keep track of the diagnostic indices, but for
now I rely on the fact that the tracer registry is in each tracer module's
control structure and we just need to track the indices of CS%Tr_reg%Tr(:)
corresponding to the desired tracers
@mnlevy1981
Copy link
Collaborator Author

After talking to @klindsay28 and @ashao, I think the next step is to reduce repeated code by having KPP_NonLocalTransport_temp() and KPP_NonLocalTransport_saln() call my new subroutine.

We also discussed the best way to pass the diagnostic IDs in to the routine, and one possibility is to just pass the entire tracer_type rather than the flat array and the ids as separate arguments. In this case, it might make sense to store the surface flux and nonlocal contribution in memory as part of the type and then post the data in MOM_tracer_registry.F90.

Introduce CFC_tracer_metadata type to remove per-tracer values in the control
structure (such as CS%CFC11_name and CS%CFC12_name)
KPP_NonLocalTransport_temp() and KPP_NonLocalTransport_saln now call
KPP_NonLocalTransport() (which is also called from the MOM_CFC_cap); this
reduces duplicate code and also adds logic to only compute the nonlocal terms
if they are either (a) being applied, or (b) being posted to diagnostics.
@mnlevy1981
Copy link
Collaborator Author

@gustavo-marques you had asked about re-running some of the CFC experiments with this branch, and I think functionally everything is ready for you to do that. Unless I have a bug somewhere subsequent pushes to this branch should be bit-for-bit refactoring or commits that add support for these nonlocal terms to other tracer modules. When you run, you need to set

CFC_APPLY_NONLOCAL_TRANSPORT = True

in your override; the default is False, which should not change answers from the previous dev/ncar head because it does not apply the nonlocal terms to the CFC tendencies. I'm happy to make the default True if that makes more sense, just let me know.

KPP_NonLocalTransport() now handles posting the budget term (if requested), and
the id for that term is available in Tr_reg%Tr(:) so it can be passed from
MOM_CFC_cap as well
The three per-tracer diagnostics added to the tracer registry (surface flux,
non-local term, and budget component of NLT) are only defined if KPP is enabled
in the diabatic driver. Note that this requires a change to MOM.F90, which may
not be desired -- the alternative is to always register the KPP diagnostics
whether KPP is enabled or not.
Added tr_ptr to the thermo_var_ptrs type, and updated MOM.F90 to have them
point to T & S correctly. There is some kludgy logic in
register_tracer_diagnostics() to register the T & S diagnostics correctly, but
I'll clean that up in a future commit. In the mean time, I was able to move
some of the diagnostic IDs out of the KPP control structure.
Had circular dependencies somewhere, so I needed to move tracer_type out of
MOM_tracer_registry.F90. I creeated MOM_tracer_types.F90 for both tracer_type
and tracer_registry_type.

Note that MOM_tracer_registry uses both of these types AND makes them public,
so other modules can continue to use them from MOM_tracer_registry instead of
needing to be changed to use them from the new module.

Also added doxygen comments to tr_T and tr_S in thermo_var_ptrs to pass the
documentation CI test.
This implementation mimics the CFC implementation, and with it I can verify
that the nonlocal term for passive tracers is NOT set up in the same manner as
it is for T & S -- there are very large differences between pseudo-salt and
real salt when PSEUDOSALT_APPLY_NONLOCAL_TRANSPORT = True
Refactored both the MOM_CFC_cap and pseudo_salt_tracer modules so that the
KPP_NonLocalTransport() call is done in {}_column_physics prior to the
tracer_vertdiff() call. This is an improvement over the previous code, but
there are still significant differences between pseudo_salt and so
Added KPP_salt_flux to forcing type, and have it point to CS%KPP_salt_flux in
the various diabatic drivers. After one day run, seeing no difference between
so and pseudo-salt when KPP is enabled.
@mnlevy1981
Copy link
Collaborator Author

mnlevy1981 commented Dec 14, 2021

I can't reproduce the failures from build-test-nans locally. I also can't figure out what actually caused the error (or how to re-run the test via github actions in case it was a weird glitch in the VM).

edit: found the "re-run all jobs" button on my branch, though it isn't available to me through the PR. Currently re-running the test

@mnlevy1981
Copy link
Collaborator Author

mnlevy1981 commented Dec 14, 2021

Okay, I reran the failing test on my branch and it passed on the second attempt. phew!

With that test passing, I think this PR is ready for more review. What I've done so far to test the changes:

  1. Prior to modifying the pseudo-salt tracer, I ran a 1-day run with hourly output and KPP%APPLY_NONLOCAL_TRANSPORT = False so I could compare so to the pseudo-salt

    • pseudo_salt_diff("Difference between pseudo salt passive tracer and salt tracer") was 0 at all time levels [previously I reported O(0.01) differences, but that's because I hadn't set APPLY_NONLOCAL_TRANSPORT correctly]
  2. Next I repeated the experiment, but with the source code from this PR and with both KPP%APPLY_NONLOCAL_TRANSPORT = True and PSEUDOSALT_APPLY_NONLOCAL_TRANSPORT = True

    • pseudo_salt_diff was still 0 at all time levels and all non-land grid points (and I verified so differed between the two runs, so I truly was turning it off in the first run)

I've also added the nonlocal terms to MOM_CFC_cap; there is still an issue of negative values in the CFC tracers in the first day, although handling the nonlocal transport before the vertical mixing does get the minimum values 2 orders of magnitude closer to 0

@mnlevy1981 mnlevy1981 marked this pull request as ready for review December 14, 2021 19:18
I was posting a diagnostic that relied on a local variable before computing the
local variable, so the diagnostic was 0 everywhere.

I also removed a couple of comments that no longer apply
@klindsay28
Copy link
Collaborator

@mnlevy1981 , can you point me to a case with negative CFC concentrations?

@mnlevy1981
Copy link
Collaborator Author

@mnlevy1981 , can you point me to a case with negative CFC concentrations?

/glade/work/mlevy/codes/CESM/cesm2_3_alpha07b/cases/CMOM.pseudosalt.003 -- the hm2 stream has hourly output from the first day

@klindsay28
Copy link
Collaborator

The following fields in that case's available_diags.000000 file have empty strings for units:
KPP_NLT_age_budget
KPP_NLT_CFC_11_budget
KPP_NLT_CFC_12_budget
KPP_NLT_pseudo_salt_budget
I think that these should have units.

Two lines were failing doxygen test because they were too long
@mnlevy1981
Copy link
Collaborator Author

@gustavo-marques I've committed all the changes we discussed during last Friday's code review. When you get a chance (I know OMWG is happening this week, so no rush!), could you run the bigger stand-alone test suite? I still need to edit the first post in this PR as well, but I think the code modifications are done.

Also, at one point you mentioned re-running the CFC experiments - would you mind spinning up one of those runs as well so we can get a feel for the effect the nonlocal terms have on the CFCs?

@gustavo-marques
Copy link
Collaborator

@mnlevy1981, I have run the MOM6-examples test suit and this PR does not change answers w.r.t. the latest main (9cb9304). I also re-started the two CFC simulations (z* and hybrid, using restarts from year 1939). I will touch base with you early next week to make sure all is good in these runs. Thanks!

@klindsay28
Copy link
Collaborator

  1. Moved tracer_type and tracer_registry_type from MOM_tracer_registry to a new MOM_tracer_types to avoid circular dependencies now that MOM_CVMix_KPP and MOM_variables now use tracer_type

Here's some additional info on the circular dependency being avoided.
Here's a sequence of use statements (with the only portion trimmed out):

./tracer/MOM_tracer_registry.F90:use MOM_diag_mediator
./framework/MOM_diag_mediator.F90:use MOM_diag_remap
./framework/MOM_diag_remap.F90:use MOM_regridding
./ALE/MOM_regridding.F90:use MOM_variables
./core/MOM_variables.F90:use MOM_tracer_types

If the types being used by MOM_variables in the last line were in MOM_tracer_registry, there would have been a circular dependence. Moving the types into MOM_tracer_types avoids this.

@mnlevy1981
Copy link
Collaborator Author

As of 900f6cf, I've merged in dev/ncar and gotten the CI tests to pass. I'm also happy with the output from aux_mom (details further down this comment). I think there is just one question to answer before merging this PR in: After discussions with @klindsay28, I moved a scale-factor that was being used when computing diagnostic values inside the KPP_NonLocalTransport_temp() and KPP_NonLocalTransport_saln() functions to the conversion argument of register_diag_field(). Ideally we'd just use

      Tr%id_NLT_budget = register_diag_field('ocean_model', Tr%NLT_budget_name, &
          diag%axesTL, Time, &
          trim(flux_longname)//' content change due to non-local transport, as calculated by [CVMix] KPP', &
          conv_units, conversion=Tr%conv_scale, v_extensive=.true.)

But for salinity, Tr%conv_scale=0.001*GV%H_to_kg_m2 and the current implementation on dev/ncar does not include that 0.001 factor. So I wrote this objectively terrible workaround inside register_tracer_diagnostics() to ensure round-off level differences in baseline comparisons rather than very large differences:

      if (Tr%conv_scale == 0.001*GV%H_to_kg_m2) then
        conversion = GV%H_to_kg_m2
      else
        conversion = Tr%conv_scale
      end if
      Tr%id_NLT_budget = register_diag_field('ocean_model', Tr%NLT_budget_name, &
          diag%axesTL, Time, &
          trim(flux_longname)//' content change due to non-local transport, as calculated by [CVMix] KPP', &
          conv_units, conversion=conversion*US%s_to_T, v_extensive=.true.)
    endif

I think we actually want one of the following two potential solutions:

  1. Add an optional KPP_NLT_budget_scale argument to register_tracer() that gets stored on Tr (and use Tr%conv_scale if it is not present)
  2. Use conv_scale and modify the units of this diagnostic for salinity. I haven't looked closely at this output, but I think the best-case scenario is that, upon inspection, we'll realize that the current units are incorrect and adding the 0.001 term is the right fix 🤞 . Otherwise I don't know how we'd get the proper units -- probably by passing an optional argument KPP_NLT_budget_units through register_tracer() that gets stored on Tr.

I know others are waiting on this PR to continue there work, though; while I don't typically advocate for merging terrible code perhaps the best path forward is to take this as-is and immediately open an issue ticket / start working on a fix


For testing, I generated a baseline for aux_mom using the most recent dev/ncar for MOM and @alperaltuntas's updates to add the DIMCS test to MOM_interface. I also modified diag_table.yaml (and json) to include KPP_QminusSW, KPP_netSalt, KPP_NLT_dTdt, KPP_NLT_dSdT, KPP_NLT_temp_budget, and KPP_NLT_saln_budget to history files (in ESCOMP/MOM_interface#103, I recommend making this modification permanent). I expected round-off level baseline failures in KPP_NLT_temp_budget and KPP_NLT_saln_budget because of the way I changed how the scale factors for these diagnostics are implemented, and I also expected rather large changes to the CFC output since we are now applying the KPP nonlocal terms to these tracers. The test suite did not disappoint:

	9	BASELINE (FAIL)
      1 DIMCS_Ld1.TL319_t061.GMOM_JRA.cheyenne_intel.mom-cfc_mods
 RMS cfc11                            3.8602E-12            NORMALIZED  4.7999E-01
 RMS cfc12                            9.7156E-13            NORMALIZED  4.5946E-01
 RMS KPP_NLT_temp_budget              9.7973E-16            NORMALIZED  4.1085E-16
 RMS cfc11_flux                       9.9943E-16            NORMALIZED  2.2481E-02
 RMS cfc12_flux                       2.4501E-16            NORMALIZED  2.1075E-02

      1 ERI_Vmct.T62_t061.GMOM.cheyenne_intel
 RMS KPP_NLT_temp_budget              9.4950E-16            NORMALIZED  4.3189E-16

      1 ERS.T62_g16.CMOM_IAF.cheyenne_intel
 RMS KPP_NLT_temp_budget              9.3795E-16            NORMALIZED  5.8756E-16

      1 ERS.T62_t061.GMOM_JRA.cheyenne_intel
 RMS KPP_NLT_temp_budget              8.5392E-16            NORMALIZED  3.7023E-16

      1 ERS.TL319_t061.GMOM_JRA_WD.cheyenne_intel
 RMS KPP_NLT_temp_budget              8.4968E-16            NORMALIZED  3.6407E-16

      1 ERS.TL319_t061_wt061.GMOM_JRA_WD.cheyenne_intel
 RMS KPP_NLT_temp_budget              8.6352E-16            NORMALIZED  3.6854E-16

      1 PET.TL319_t061.GMOM_JRA.cheyenne_intel
 RMS KPP_NLT_temp_budget              9.2954E-16            NORMALIZED  3.6926E-16

      1 SMS_D.T62_t061.GMOM_IAF.cheyenne_intel
 RMS KPP_NLT_temp_budget              1.0020E-15            NORMALIZED  4.7087E-16

      1 SMS_Ld40.T62_t061.CMOM_IAF.cheyenne_intel
 RMS KPP_NLT_temp_budget              9.5077E-16            NORMALIZED  4.7229E-16
 RMS KPP_NLT_temp_budget              9.0976E-16            NORMALIZED  4.8688E-16

I also ran a one-off test where I compared output from a run with CFCs and pseudosalt to a baseline generated by my branch before merging dev/ncar and got bit-for-bit results, so I think the large differences in cfc11, cfc12, cfc11_flux, and cfc12_flux are okay. (As noted in #211, I needed to add two variables to MOM_override to get the bit-for-bit results.)

The DIMCS scaling tests all passed:

PASS DIMCS_Ld1.TL319_t061.GMOM_JRA.cheyenne_intel.mom-cfc_mods COMPARE_dimscale_1_Tp_base
PASS DIMCS_Ld1.TL319_t061.GMOM_JRA.cheyenne_intel.mom-cfc_mods COMPARE_dimscale_2_Lp_base
PASS DIMCS_Ld1.TL319_t061.GMOM_JRA.cheyenne_intel.mom-cfc_mods COMPARE_dimscale_3_Hp_base
PASS DIMCS_Ld1.TL319_t061.GMOM_JRA.cheyenne_intel.mom-cfc_mods COMPARE_dimscale_4_Zp_base
PASS DIMCS_Ld1.TL319_t061.GMOM_JRA.cheyenne_intel.mom-cfc_mods COMPARE_dimscale_5_Rp_base
PASS DIMCS_Ld1.TL319_t061.GMOM_JRA.cheyenne_intel.mom-cfc_mods COMPARE_dimscale_6_Qp_base
PASS DIMCS_Ld1.TL319_t061.GMOM_JRA.cheyenne_intel.mom-cfc_mods COMPARE_dimscale_7_Tn_base
PASS DIMCS_Ld1.TL319_t061.GMOM_JRA.cheyenne_intel.mom-cfc_mods COMPARE_dimscale_8_Ln_base
PASS DIMCS_Ld1.TL319_t061.GMOM_JRA.cheyenne_intel.mom-cfc_mods COMPARE_dimscale_9_Hn_base
PASS DIMCS_Ld1.TL319_t061.GMOM_JRA.cheyenne_intel.mom-cfc_mods COMPARE_dimscale_10_Zn_base
PASS DIMCS_Ld1.TL319_t061.GMOM_JRA.cheyenne_intel.mom-cfc_mods COMPARE_dimscale_11_Rn_base
PASS DIMCS_Ld1.TL319_t061.GMOM_JRA.cheyenne_intel.mom-cfc_mods COMPARE_dimscale_12_Qn_base

Full disclosure, there were two surprises in the testing output. First, there were a couple of BASELINE passes:

	2	BASELINE (PASS)
      1 SMS_Ld2.f09_t061.B1850MOM.cheyenne_intel.mom-bmom
      1 SMS.T62_t025.CMOM.cheyenne_intel

The SMS.T62_t025.CMOM.cheyenne_intel pass is expected, as USE_KPP = False. The B1850MOM case does use KPP, and the NLT budget terms look reasonable in it so I didn't spend too much time investigating the pass.

The other surprise is that ERS.TL319_t061.GMOM_JRA_WD.cheyenne_intel and ERS.TL319_t061_wt061.GMOM_JRA_WD.cheyenne_intel had additional BASELINE failures due to not finding the baseline for the ww3.hi history file:

File '${CASE}.ww3.hi.0001-01-12-00000.nc' had no compare counterpart in '${BASELINE_DIR}' with suffix ''

This seems like an issue with how the test suite is configured, but it looks like these tests will continue to fail even when all the history output found is bit-for-bit.

@mnlevy1981
Copy link
Collaborator Author

After talking with @klindsay28, I have one more commit coming that will clean up a couple of comments and then this will be ready to be reviewed / merged. It might make sense to squash-merge it instead of keeping the 32 commit history of the branch.

Re: the convergence scale kludge I mentioned in my previous commit -- we want to leave it in place for this PR but @klindsay28 will remove it when he cleans up the diagnostic framework.

Units were incorrect in comment describing cfc11_flux and cfc12_flux. Also,
updated comment surrounding the kludge in the conversion term when registering
the NLT_budget diagnostics for each tracer.
@mnlevy1981
Copy link
Collaborator Author

After talking with @klindsay28, I have one more commit coming that will clean up a couple of comments and then this will be ready to be reviewed / merged.

3e4f827 was the "one more commit". All CI tests are passing, aux_mom results are listed above, and this is ready for review.

src/tracer/MOM_tracer_types.F90 Show resolved Hide resolved
@@ -251,7 +251,7 @@ module MOM_diabatic_driver
real, allocatable, dimension(:,:,:) :: KPP_buoy_flux !< KPP forcing buoyancy flux [L2 T-3 ~> m2 s-3]
real, allocatable, dimension(:,:) :: KPP_temp_flux !< KPP effective temperature flux
!! [degC H T-1 ~> degC m s-1 or degC kg m-2 s-1]
real, allocatable, dimension(:,:) :: KPP_salt_flux !< KPP effective salt flux
real, pointer, dimension(:,:) :: KPP_salt_flux => NULL() !< KPP effective salt flux
Copy link
Member

Choose a reason for hiding this comment

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

Is there a reason to convert this array to a pointer? GFDL has recently replaced many pointer declarations in MOM6 as either allocatables or locals for improving the performance: NOAA-GFDL#5
So, unless there is a limitation for using an allocable array herer, I suggest keeping it an allocatable array

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The salt flux is also needed in the pseudosalt module, and so I added a pointer for it to forcing_type and then the diabatic driver ensures the forcing_type pointer points to this field.

Copy link
Member

Choose a reason for hiding this comment

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

Thanks. Now that makes me wondering why KPP_salt_flux is a part of diabatic_CS. If it was a member of KPP_CSp instead, then you wouldn't need to make it a pointer or add it to forcing_type. The same goes for KPP_NLTheat and other KPP_* data above. Why are they not a part of the KPP module? Anyway, these can be deemed outside the scope of this PR, but KPP_salt_flux being a part of KPP_CSp would simplify this PR a bit.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks. Now that makes me wondering why KPP_salt_flux is a part of diabatic_CS. If it was a member of KPP_CSp instead, then you wouldn't need to make it a pointer or add it to forcing_type. The same goes for KPP_NLTheat and other KPP_* data above. Why are they not a part of the KPP module? Anyway, these can be deemed outside the scope of this PR, but KPP_salt_flux being a part of KPP_CSp would simplify this PR a bit.

I think this would be an interesting discussion for one of the MOM meetings with GFDL, or maybe via an issue ticket on the mom-ocean repo? I agree that refactoring this in a way that would let us pass the data to pseudosalt without the addition to forcing_type would be an improvement over what is in this PR

@klindsay28
Copy link
Collaborator

klindsay28 commented Mar 2, 2022 via email

Code review pointed out that netSalt had been removed from the forcing type on
dev/ncar, but I inadvertantly added it back in. Also removed commented out
lines referring to the now-removed variable.
@mnlevy1981
Copy link
Collaborator Author

mnlevy1981 commented Mar 3, 2022

728fe16 addressed @klindsay28's comment about netSalt; I think the rest of the comments were resolved with "let's discuss this in the future" or "let's open an issue ticket after this PR is on dev/ncar", so if I missed a comment that needs more code mods please let me know.

Copy link
Collaborator

@klindsay28 klindsay28 left a comment

Choose a reason for hiding this comment

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

I agree that the remaining points that I raised are beyond the scope of this PR. So I think it is ready to be merged.

I like the idea of merging this PR as a squash merge. This would reduce the clutter from the many commits, and I only see a minimal benefit from separating commits. The only commit that I see worth considering separately is the movement of tracer_type from MOM_tracer_registry.F90 to MOM_tracer_types.F90, and I don't see its separation as necessary. I think the main challenge is to write a commit message for the squash merge that fully describes what the PR does.

Two items to consider beyond this PR:

  1. @alperaltuntas's suggestion of moveng KPP specific fields, like KPP_salt_flux, from the forcing type to the KPP_CS type.
  2. Add a rotation test, with KPP enabled, to aux_mom and/or github actions testing. There are rotation tests in github actions testing, but I don't think any of those enable KPP.

@mnlevy1981
Copy link
Collaborator Author

mnlevy1981 commented Mar 7, 2022

I agree that the remaining points that I raised are beyond the scope of this PR. So I think it is ready to be merged.

I like the idea of merging this PR as a squash merge. This would reduce the clutter from the many commits, and I only see a minimal benefit from separating commits.

I also think that this should be a squash-merge; a reasonable commit message for it would be

Support for KPP Nonlocal term beyond T & S

When APPLY_NONLOCAL_TRANSPORT=True, the KPP Nonlocal term will be applied to
the tracers in the MOM_CFC_cap module and the tracer in the pseudo_salt_tracer
module (if they are active in the run).

To support this, some of the KPP diagnostics were moved from the KPP_CS type to
the tracer_type data structure and the KPP_NonLocalTransport_temp() and
KPP_NonLocalTransport_saln() functions were refactored to put common code in
KPP_NonLocalTransport() (which can be called from any of the tracer modules).

Additionally, scaling terms for the diagnostics available from the
KPP_NonLocalTransport() function are encoded via the conversion argument of the
register_diag_field() call in register_tracer_diagnostics(). This results in a
round-off level change to the KPP_NLT_temp_budget and KPP_NLT_saln_budget
diagnostics.

Lastly, two structural changes to the code:
1. To avoid a circular dependency between MOM_variables.F90 and
   MOM_tracer_registry.F90, tracer_type and tracer_registry_type have been
   moved to a new module named MOM_tracer_types.F90. Both of those types remain
   public in MOM_tracer_registry.F90, so they are still available through "use
   MOM_tracer_registry" statements.
2. Some code in MOM_CFC_cap.F90 was refactored to replace nearly-repeated lines
   (first for CFC11 and then for CFC12) with loops over an array of the new
   CFC_tracer_metadata type.

I'm open to suggestions / improvements on that, but I think it touches all the key points of this PR.

@klindsay28
Copy link
Collaborator

@mnlevy1981, maybe mention in the overall message that there is cleanup in the MOM_CFC_cap module that replaces some (nearly) repeated lines of code with loops over the module's tracers.

@mnlevy1981
Copy link
Collaborator Author

@mnlevy1981, maybe mention in the overall message that there is cleanup in the MOM_CFC_cap module that replaces some (nearly) repeated lines of code with loops over the module's tracers.

Good catch! I have edited my comment containing the commit message to include these changes, because that seems less confusing than having multiple drafts of the commit message in different comments in this PR.

It also reminds me of some clean-up that should wait for a future PR, but it doesn't really make sense to have tracer concentration in a type named CFC_tracer_metadata (it doesn't seem like metadata to me). So a future issue to address would be to pull conc out of that type and have both CS%CFC_metadata(:) and CS%CFC_concentration(:) (or CFC_conc(:) or just plain conc(:))

@mnlevy1981
Copy link
Collaborator Author

It also reminds me of some clean-up that should wait for a future PR, but it doesn't really make sense to have tracer concentration in a type named CFC_tracer_metadata (it doesn't seem like metadata to me). So a future issue to address would be to pull conc out of that type and have both CS%CFC_metadata(:) and CS%CFC_concentration(:) (or CFC_conc(:) or just plain conc(:))

I was thinking about addressing this while waiting for the updates needed for @gustavo-marques to run the stand-alone regression tests, and one potential solution would be to just rename CFC_tracer_metadata to CFC_tracer_data and the corresponding variable in the control structure CFC_data instead of CFC_metadata.

diff --git a/src/tracer/MOM_CFC_cap.F90 b/src/tracer/MOM_CFC_cap.F90
index a80221e4a..22788c896 100644
--- a/src/tracer/MOM_CFC_cap.F90
+++ b/src/tracer/MOM_CFC_cap.F90
@@ -36,9 +36,8 @@ module MOM_CFC_cap

 integer, parameter :: NTR = 2 !< the number of tracers in this module.

-!> Contains per-tracer metadata and a pointer to Tr in Tr_reg
-type, private :: CFC_tracer_metadata
-  ! The following vardesc types contain a package of metadata about each tracer.
+!> Contains the concentration array, a pointer to Tr in Tr_reg, and some metadata for a single CFC tracer
+type, private :: CFC_tracer_data
   type(vardesc) :: desc !< A set of metadata for the tracer
   real :: IC_val = 0.0    !< The initial value assigned to the tracer [mol kg-1].
   real :: land_val = -1.0 !< The value of the tracer used where land is masked out [mol kg-1].
@@ -46,7 +45,7 @@ module MOM_CFC_cap
   integer :: id_cmor  !< Diagnostic ID
   real, pointer, dimension(:,:,:) :: conc  !< The tracer concentration [mol kg-1].
   type(tracer_type), pointer :: tr_ptr !< pointer to tracer inside Tr_reg
-  end type CFC_tracer_metadata
+  end type CFC_tracer_data

 !> The control structure for the CFC_cap tracer package
 type, public :: CFC_cap_CS ; private
@@ -61,7 +60,7 @@ module MOM_CFC_cap
                                              !! the timing of diagnostic output.
   type(MOM_restart_CS), pointer :: restart_CSp => NULL() !< Model restart control structure

-  type(CFC_tracer_metadata), dimension(2) :: CFC_metadata !< per-tracer parameters / metadata
+  type(CFC_tracer_data), dimension(2) :: CFC_data        !< per-tracer parameters / metadata
 end type CFC_cap_CS

 contains

(I didn't show every single CFC_metadata -> CFC_data change in the code, but it's contained to MOM_CFC_cap.F90)

Does anyone have strong feelings about whether or not I should push this change? My plan would be to build and run a single case with CFCs enabled to ensure bit-for-bit against a baseline rather than the full aux_mom test suite -- the nature of this change makes me think the most likely way to mess it up would prevent the model from building at all, and a single case with CFCs enabled that does not change answers would be sufficient to convince me the find / replace worked as expected.

CFC_tracer_metadata contains data that isn't actually metadata (the actual
concentration array; a pointer to the tracer_type in Tr_reg); this commit
cleans up the naming of both the type and the variable of the type used in the
control structure (it is now CFC_data instead of CFC_metadata)
The main doxygen description of MOM_tracer_registry.F90 claimed that
tracer_registry_type was defined in that module, but it was moved to
MOM_tracer_types.F90
@gustavo-marques
Copy link
Collaborator

This PR does not change answers for MOM6-examples when compared against MOM6/main.
There is a minor change in MOM_parameter_doc.all for the following tests because the description of APPLY_NONLOCAL_TRANSPORT has been updated:

	ocean_only/CVmix_SCM_tests/cooling_only/KPP/
	ocean_only/CVmix_SCM_tests/mech_only/KPP/
	ocean_only/CVmix_SCM_tests/skin_warming_wind/KPP/
	ocean_only/CVmix_SCM_tests/wind_only/KPP/
        ocean_only/SCM_idealized_hurricane/
	ocean_only/SCM_idealized_hurricane/
	ocean_only/single_column/EPBL/
	ocean_only/single_column/KPP/

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.

5 participants