NOAA-GFDL / xwmt

Python package for water mass transformation analysis that leverages xarray functionality
https://xwmt.readthedocs.io/
MIT License
7 stars 5 forks source link

Assigning attributes to flux/tendency terms rather than using a master dictionary #13

Open gmacgilchrist opened 2 years ago

gmacgilchrist commented 2 years ago

To evaluate the WMT from a given flux or tendency term, you need to convert it from whatever form it is in into h*ldot (where h is the thickness of the cell, and ldot is the tendency of the intensive scalar value e.g. temperature). The current configuration of the code uses a master dictionary (dd) to attach particular characteristics to particular processes.

The necessary characteristics are:

  1. The scalar quantity that the flux/tendency is associated with (e.g.
  2. Whether it is a flux or a tendency
  3. Whether it is for the intensive or extensive quantity
  4. Whether it is associated with a boundary mass flux

    If associated with a mass flux, you need to also know (a) what is the scalar quantity in the mass flux and (b) what is the scalar quantity at the boundary.

Perhaps a more robust and generalizable approach would be to assign attributes to the DataArrays that are associated with each flux/tendency term in the input Dataset. So, for example, assigning these attributes to the DataArray for hfds (flux of extensive quantity associated with temperature and no boundary mass flux). In that way, the DataArray can easily carry these attributes with it as it is passed through the functions of the package. Each function that requires knowledge of the form of the tendency/flux can simply grab its .attrs. A user could independently assign the relevant properties to each flux or tendency in their Dataset before initializing the swmt class. Alternatively, if the fluxes or tendencies have CMOR names, the attributes could be assigned automatically on initialization.

Just a thought that can be picked up or not moving forward. (Also, I know that the master dictionary set-up was inherited from the initial skeleton package, so I accept full responsibility for its relative clunkiness.)

hdrake commented 1 year ago

I think this change makes sense.

hdrake commented 1 year ago

@gmacgilchrist and @jetesdal, what do you guys think about the following budgets_dict dictionary structure:

heat:
    lambda: "thetao"
    surface_lambda: "tos"
    lhs:
        total: "opotemptend"
    rhs:
        total: null
        terms:
            advection:
                total: null
                terms:
                    horizontal_advection: "T_advection_xy"
                    vertical_advection: "Th_tendency_vert_remap"
            diffusion:
                total: null
                terms:
                    vertical_diffusion: "opottempdiff"
                    neutral_diffusion: "opottemppmdiff"
            diabatic_forcing:
                total: null
                terms:
                    frazil_ice: "frazil_heat_tendency"
                    geothermal: "internal_heat_heat_tendency"
                    boundary_forcing:
                        total: "boundary_forcing_heat_tendency"
                        flux_terms:
                            latent: "hflso"
                            sensible: "hfsso"
                            longwave: "rlntds"
                            shortwave: "rsdo"
                            frazil_ice: "hfsifrazil"
                            mass_transfer: "heat_content_surfwater"
                            basal: null

This way the logic of how to decompose/reconstruct the tracer/watermass budget is built in to the class metadata, including both high-level aggregate terms like the total "diabatic_forcing" but then also all of the various terms that contribute to it.

This would replace the currently clunky ways we've been handling this, e.g. in @jetesdal's version and mine

gmacgilchrist commented 1 year ago

I like this @hdrake.

Not for now, but a consideration for the future would be that you could conceivably calculate any of the tendencies from the divergence of their contributing fluxes. So, I wonder if there should be a flux_terms for each of the terms. E.g.

advection:
                total: null
                terms:
                    horizontal_advection: 
                        total: "T_advection_xy"
                        flux_terms:
                            x: "T_adx"
                            y: "T_ady"

This could provide a nice overarching framework for laying out budget closure more generally (e.g. the WaterMass class could have a .check_closure, that confirms that all of the relevant terms are present and close the budget; of course, no reason why this can't already be done with the tendency terms too).

hdrake commented 1 year ago

I like this @hdrake.

Not for now, but a consideration for the future would be that you could conceivably calculate any of the tendencies from the divergence of their contributing fluxes. So, I wonder if there should be a flux_terms for each of the terms. E.g.

advection:
                total: null
                terms:
                    horizontal_advection: 
                        total: "T_advection_xy"
                        flux_terms:
                            x: "T_adx"
                            y: "T_ady"

This could provide a nice overarching framework for laying out budget closure more generally (e.g. the WaterMass class could have a .check_closure, that confirms that all of the relevant terms are present and close the budget; of course, no reason why this can't already be done with the tendency terms too).

Yes, that's a nice idea—I hadn't though of doing it for horizontal flux divergences. A .check_closure method was already something I had in mind with this.

hdrake commented 1 year ago

Thanks to feedback from @gmacgilchrist @jetesdal @StephenGriffies, the comprehensive dictionary that describes the MOM6 tracer budgets in great detail now lives in a new package, xbudget. The package also includes some utility functions for extracting actionable information from the long and otherwise difficult-to-parse dictionary. These are illustrated in both an xbudget example and a new and improved introductory xwmt example.