MetPy icon indicating copy to clipboard operation
MetPy copied to clipboard

Implement convective condensation level (CCL)

Open Z-Richard opened this issue 3 years ago • 6 comments

Description Of Changes

This PR implemented the convective condensation level (CCL), with options to use either the surface mixing ratio or the average mixing ratio over a shallow layer near the surface, according to the definition of CCL by AMS.

I also wrote a bunch of tests to make sure that what I implemented is correct using UWYO sounding. I can't find any existing software to compare my CCL calculations to, so I just eyeballed the desired values from the Skew-T diagrams.

Sorry for creating a new PR -- it turns out that I messed up with git for the last PR, and opening a new one seems the best option.

Checklist

  • [x] Closes #1731
  • [x] Tests added
  • [x] Fully documented

Z-Richard avatar Jun 24 '22 02:06 Z-Richard

@dopplershift @dcamron Hi MetPy developers -- I would really appreciate it if I could get some feedback on this PR. The math here is pretty straightforward:

  • We can plug in the mixing ratio equation to the saturation vapor pressure equation and obtain a T(p) relationship in an atmosphere with a constant r. Although we can't directly solve for T, we can express the relationship in a form of A(P)=B(T) and obtain the temperature in two steps (a_p and rt_profile in the function). Both the mixing ratio equation and the saturation vapor pressure equation are consistent with what MetPy currently has.
  • Then find_intersections would come in handy, as we have both an ambient temperature profile and a temperature profile with constant r. The users may choose which CCL level to return, and I have set the default to top (lowest pressure, which is consistent with LFC).

The tests provide decent coverage for the function, although there are a few caveats. I basically grabbed some sounding data from siphon and used the arrays directly in the tests. I think it's better to leave it at that than to import siphon for testing because the additional dependency can be tricky to deal with. I'm also a little lazy to not write a test to validate the correctness of the height parameter, which is directly passed onto the mixed_layer function and thus should not have any issues if mixed_layer is implemented correctly. I can write an additional test if this is necessary.

Please let me know if there is anything else I can do to improve my code. Thanks for reviewing this PR!

Z-Richard avatar Jun 30 '22 02:06 Z-Richard

Thanks for the PR and the explanation! Grabbing arrays from siphon is perfect for the tests. I'll comment on explicitly testing height once I review, but you're right that it likely doesn't need it. I do plan on reviewing this and we can include it in for our feature release scheduled for the end of this month.

dcamron avatar Jul 07 '22 16:07 dcamron

The derivation for CCL. The T in the last step is the temperature profile with a constant mixing ratio.

image

Z-Richard avatar Sep 16 '22 01:09 Z-Richard

Oh, there's one more consideration: I'm not sold on the need to build in the mixed layer approach. We don't do it in much else (like lcl), with the lone exception being mixed_layer_cape_cin. I think I'd prefer to keep the implementation simpler.

Is the need for this that mixed_layer operates properly on mixing ratio, and we ask users to pass in dewpoint?

dopplershift avatar Sep 16 '22 23:09 dopplershift

Thanks for the suggestion! I should have speculated that this was implemented somewhere in MetPy, but I would have never figured out what those globals() mean on my own.

I agree that we should simplify the function by not using the mixed layer approach, but I got this definition from AMS. There may be folks in AMS who want to adhere to their own definition of CCL, and I think the function should still be reasonably simple to use if we add an example to show what the default behavior looks like (i.e. use surface dewpoint instead of a mixed layer.) Again, I am good with going either direction, so it might be your call to decide which way is better for our users.

And as a last note, I will be adding some examples after we have settled down on whether we should use a mixed layer approach. These examples will make life much easier for our users.

Z-Richard avatar Sep 19 '22 01:09 Z-Richard

And one last thing: I just realized that the unit handling in this function is terribly wrong but somehow escapes the test cases. It seems that assert_almost_equal in metpy.testing thinks that two values are equal to each other even if their units are different. This is rather bizarre, and at this point, I am not sure about what is the correct way to test units, so people might need to check that as well.

Z-Richard avatar Sep 19 '22 02:09 Z-Richard

Quick ping @dopplershift

Z-Richard avatar Sep 28 '22 12:09 Z-Richard

@Z-Richard based on our discussion on today's MetPy dev call (which anyone is welcome to join), we can keep the direct implementation of the mixed layer support since it seems like it would be a really common use case for the tool. So feel free to add some examples demonstrating this.

I'll dig into the unit issue you encountered and see what's up there.

dopplershift avatar Sep 29 '22 20:09 dopplershift

@dopplershift Never mind the unit issue. It turns out that I should also add assert input.units == output.units to explicitly test for unit, and I was just implicitly thinking that assert_almost_equal would throw an AssertionError when two values have different units. I will add the appropriate tests using the pattern above, and we should be good to go.

Z-Richard avatar Sep 29 '22 22:09 Z-Richard

I was just implicitly thinking that assert_almost_equal would throw an AssertionError when two values have different units.

Ah, yeah the converter is just smart enough to first make sure to convert things to a common unit and then check the values.

dopplershift avatar Sep 29 '22 22:09 dopplershift

I think it would be worth the effort to bundle LCL, LFC and CCL into a single example gallery as a separate PR because it makes the most sense to introduce all three functionalities at once. For this PR, a docstring example might suffice.

Z-Richard avatar Sep 29 '22 22:09 Z-Richard

#2629 is adding a bunch of examples, including one with all the indices, might make sense to add this there (cc @kgoebber) since I sense this is getting merged shortly.

Adding a docstring example will be fine, you're right.

dopplershift avatar Sep 29 '22 22:09 dopplershift

One last question: should the docstring description

This function is implemented directly based on the definition of the CCL,
as in [USAF1990]_, and finding where the ambient temperature profile
intersects the line of constant mixing ratio starting at the surface,
using the surface dewpoint.

also reflect the fact that users can use a mixed layer dewpoint to compute CCL? I haven't looked into the USAF manual myself and am not 100% sure that the mixed-layer approach is mentioned there.

Z-Richard avatar Sep 29 '22 23:09 Z-Richard

The manual (4.18 and 4.19) says

When there is much variation in moisture content in the layers near the surface, an average moisture value of the lower layer may be used in place of the surface-parcel moisture value in computing the CCL.

I think it's fine to mention the option to use a mixed layer and still be consistent with the reference.

dopplershift avatar Sep 30 '22 00:09 dopplershift

This should be good to go in. Could you do a final check?

Z-Richard avatar Sep 30 '22 00:09 Z-Richard