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

Conservation checker interface #167

Merged
merged 1 commit into from
Dec 10, 2022
Merged

Conversation

LenkaNovak
Copy link
Collaborator

@LenkaNovak LenkaNovak commented Nov 21, 2022

Purpose

Move existing energy check to src and extend to water conservation.

Content

  • ConservationChecker module
  • move energy checker code to src
  • extend energy checker to water mass
  • add unit tests for accumulator
  • add unit tests for visualization
  • demonstrate implementation in a new driver (coupler-driver_modular.jl)
  • add buildkite hook
  • add documentation

Notes

  • the energy check plots in Buildkite are identical to those produced using the non-modularized version of the conservation checker, called by coupler_driver.jl.
  • conservation is not to the required precision. Investigating this is already a TODO in AMIP improvements #135
  • generalizing the contained functions further requires a re-design of our simulation objects. This will be deferred to the upcoming SDI on optimization and performance.

  • I have read and checked the items on the review checklist.

@LenkaNovak LenkaNovak mentioned this pull request Nov 21, 2022
13 tasks
@LenkaNovak LenkaNovak force-pushed the ln/conservationchecker-interface branch 3 times, most recently from cebcc63 to db64044 Compare December 8, 2022 16:06
@LenkaNovak LenkaNovak marked this pull request as ready for review December 8, 2022 16:07
@LenkaNovak LenkaNovak force-pushed the ln/conservationchecker-interface branch from db64044 to b739663 Compare December 8, 2022 16:33
@LenkaNovak LenkaNovak changed the title Conservation checker interface (WIP) Conservation checker interface Dec 8, 2022
@LenkaNovak LenkaNovak requested a review from szy21 December 8, 2022 16:34
Copy link
Member

@szy21 szy21 left a comment

Choose a reason for hiding this comment

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

Thanks Lenka! I only quickly went through it because it's a large PR:) I left a few comments. Also, I wonder if it makes sense to add mass conservation as well?

FT = eltype(coupler_sim.surface_masks.land)

# save radiation source
if radiation != nothing
Copy link
Member

Choose a reason for hiding this comment

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

We have this in ClimaAtmos which integrates fluxes at the boundaries. It might be useful when you clean up the code.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That's great! We can update to this upon the next ClimaAtmos release.


Only energy and water are currently implemented.

Note that kinetic energy is not included in the calculation of the global energy, reflecting the formulation on `ClimaAtmos`, which assumes that kinetic energy is negligible in comparison with the moist static energy components.
Copy link
Member

Choose a reason for hiding this comment

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

I think this is a bit confusing because e.g. when you calculate the total energy of atmosphere using e_tot, it includes kinetic energy. Maybe rephrase it as something like Kinetic energy transfer between atmosphere, land, and ocean is not included?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That was rather misleading, thanks for pointing it out! It was meant to refer to the KE contribution being neglected in all diffusive fluxes in the atmos interior, so this is consistent with these BCs. In any case, since we won't be needing this function (except perhaps for diagnostics?) in the foreseeable, I've decided to remove it for now. :P

evaporation = cs.fields.F_E # kg/m^2/s / layer depth
precipitation_l = cs.fields.P_liq
precipitation_s = cs.fields.P_snow
@. (evaporation + precipitation_l + precipitation_s) * cs.Δt_cpl # in kg
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
@. (evaporation + precipitation_l + precipitation_s) * cs.Δt_cpl # in kg
@. (evaporation + precipitation_l + precipitation_s) * cs.Δt_cpl # in kg /m^2

I think that's the unit? I'm not sure though.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

see above. Now clarified

end

# save ocean
if ice_sim !== nothing
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if ice_sim !== nothing
if ocean_sim !== nothing

?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good catch! I missed this after the last rebase! 😳

if land_sim !== nothing
water_content =
@. (land_sim.integrator.u.bucket.σS + land_sim.integrator.u.bucket.W + land_sim.integrator.u.bucket.Ws) # m^3 water / land area / layer height
parent(water_content) .= parent(water_content .* surface_masks.land) * FT(1000)
Copy link
Member

Choose a reason for hiding this comment

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

It's a bit hard for me to figure out the unit here (without knowing details about the land model). Maybe add some more comments?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sure! I can comment more lines. Also, instead of the FT(1000), I'm adding ClimaLSM.LSMP.ρ_cloud_liq which clarifies the units further. The final values are in kg, thanks to ClimaCore's sum function doing the volume integral for us (rather than a simple sum).

@@ -0,0 +1,8 @@
[land_mask]
Copy link
Member

Choose a reason for hiding this comment

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

do we want the artifacts to be checked in to github? I'm not sure it matters too much, just wanted to double check

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I would have thought it would be good to keep it for tracking changes in the files (each time the file is replaced with a new one of the same name, the git-tree-sha1 changes). I just found this issue, which may require using Tar.tree_hash to be general to all platforms, but apparently this should have been fixed in Julia 1.6. @charleskawczynski do you have any thoughts? I noticed Atmos doesn't check these in?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, I think the artifacts toml is the intended file to be tracked, so that there's a direct mapping between these hashes and the artifacts used.

We don't in ClimaAtmos, but we probably should.

Also, I haven't seen that issue before, it could be that we somehow need to update ArtifactWrappers to use this

Copy link
Member

Choose a reason for hiding this comment

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

For now, I think checking it in is fine, it at least enforces some reproducibility

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thank you, Charlie!

end

## read in some parsed command line arguments
mode_name = parsed_args["mode_name"]
Copy link
Member

Choose a reason for hiding this comment

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

maybe not now, but we could consider reading in parsed_args as a NamedTuple, then using the (; ...) syntax to unpack it more concisely


# import coupler utils
include("coupler_utils/flux_calculator.jl")
include("coupler_utils/regridder.jl") # update_midmonth_data!
Copy link
Member

Choose a reason for hiding this comment

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

I think we don't need this since the Regridder module should have all the functionality of the regridder util. If we still have the include, we might not be actually using the functions from Regridder


using ClimaCoupler.Utilities
using ClimaCore: ClimaCore, Geometry, Meshes, Domains, Topologies, Spaces, Fields, InputOutput
using ClimaCore.Utilities: half
Copy link
Member

Choose a reason for hiding this comment

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

I think this is redundant since you already have using ClimaCoupler.Utilities

Copy link
Collaborator Author

@LenkaNovak LenkaNovak Dec 9, 2022

Choose a reason for hiding this comment

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

Actually the half needs to be specifically imported, but line 8 can be removed. :)

"""
check_conservation!(coupler_sim::CoupledSimulation)

itertes over all specified conservation checks.
Copy link
Member

Choose a reason for hiding this comment

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

docstring doesn't match function signature

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good catch!

map(x -> check_conservation!(x, coupler_sim, get_slab_energy, get_land_energy), coupler_sim.conservation_checks)

"""
check_conservation!(
Copy link
Member

Choose a reason for hiding this comment

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

docstring doesn't match function signature


Calculate the kinetic energy diffipation of a simulation.
"""
function ke_dissipation(sim)
Copy link
Member

Choose a reason for hiding this comment

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

could be helpful to annotate the input and return types (at least in the docstring)

Copy link
Collaborator Author

@LenkaNovak LenkaNovak Dec 9, 2022

Choose a reason for hiding this comment

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

This function is now removed (see above).

end

"""
check_conservation(
Copy link
Member

Choose a reason for hiding this comment

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

docstring doesn't match function signature

end

# https://github.com/jheinen/GR.jl/issues/278#issuecomment-587090846
ENV["GKSwstype"] = "nul"
Copy link
Member

Choose a reason for hiding this comment

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

a short comment explaining why this is here could be helpful, then readers can follow the link for more detail

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sure!

@LenkaNovak
Copy link
Collaborator Author

@szy21 and @juliasloan25 , thank you both for the review! 🚀

@LenkaNovak
Copy link
Collaborator Author

LenkaNovak commented Dec 9, 2022

We can do, but I'm not sure we're exchanging anything else but water between the models right now, so maybe domain-local conservation checks should be done in the models themselves?

@szy21
Copy link
Member

szy21 commented Dec 9, 2022

We can do, but I'm not sure we're exchanging anything else but water between the models right now, so maybe domain-local conservation checks should be done in the models themselves?

Yes, I just thought it would be more comprehensive and might be useful for debugging to have all the conservation checks (mass, energy, water) when running the coupled simulation. But you're right there is no mass exchange between atmos and land or ocean, so we can do it in ClimaAtmos.

@LenkaNovak LenkaNovak force-pushed the ln/conservationchecker-interface branch from b739663 to 223542b Compare December 9, 2022 17:46
@LenkaNovak
Copy link
Collaborator Author

LenkaNovak commented Dec 9, 2022

It's really no problem to add it in here temporarily, if it's useful. But in the long term we should probably have checks for both coupled and standalone runs. I'll put it on the AMIP improvements list and maybe we can reassess in Jan?

tests for all except land_sea_mask

all tests pass, land_sea_mask separated

before Project.toml cleanup

Project.tomls cleaned up

cleanup

GeneralUtilities, TestHelper modules

docs and formatting

modularize conservation checker

wip

passing tests

clean + doc

doc

trigger test

docs

rebase

plots rebase fix

dep + buildkite

buildkite fix

plots dep unavoidable

pip fix

tests

deps

redundant func fix

fix

revs

SB Manifest
@LenkaNovak LenkaNovak force-pushed the ln/conservationchecker-interface branch from 223542b to 5055449 Compare December 9, 2022 23:31
@LenkaNovak
Copy link
Collaborator Author

bors r+

@bors
Copy link
Contributor

bors bot commented Dec 10, 2022

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.

4 participants