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

Update constants to CODATA 2018 #235

Merged
merged 1 commit into from
Jun 17, 2019
Merged

Conversation

sostock
Copy link
Collaborator

@sostock sostock commented May 20, 2019

This updates the physical constants to use the 2018 CODATA recommended values.

@codecov-io
Copy link

codecov-io commented May 20, 2019

Codecov Report

Merging #235 into master will not change coverage.
The diff coverage is n/a.

Impacted file tree graph

@@           Coverage Diff           @@
##           master     #235   +/-   ##
=======================================
  Coverage   74.37%   74.37%           
=======================================
  Files          14       14           
  Lines        1073     1073           
=======================================
  Hits          798      798           
  Misses        275      275
Impacted Files Coverage Δ
src/pkgdefaults.jl 21.27% <ø> (ø) ⬆️

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 45a5dff...497662a. Read the comment docs.

@giordano
Copy link
Collaborator

It would be awesome if there were a mechanism to select the set of constants used, also for backward compatibility

@sostock
Copy link
Collaborator Author

sostock commented Jun 7, 2019

@giordano Yes, that might be useful. I guess the easiest way to implement this would be like in your PhysicalConstants package, i.e., create submodules Unitful.CODATA2014 and Unitful.CODATA2018 in which these constants/units are defined. (Or do you have a better idea?)

Of course, users would then have to change their code, since they can no longer use these constants without using one of these submodules. But I think that’s fine. One could still debate whether constants that didn’t change between CODATA2014 and CODATA2018 (like c0) should be available without loading one of the submodules.

We should probably also think about whether (and how) we want to enforce consistency between Unitful and PhysicalConstants, i.e., I think one should not be able to load Unitful.CODATA2018 together with PhysicalConstants.CODATA2014.

What are your thoughts on this?

@giordano
Copy link
Collaborator

Actually, PhysicalConstants.jl is mostly an implementation of #81 (as mentioned also in #186).

While using the new dataset PhysicalConstants.CODATA2018 I noted that converting constants in other units would give incorrect results as Unitful.jl is currently using constants from CODATA2014. However, I don't have in mind an idea about how Unitful.jl could expose different datasets (perhaps always defaulting to the latest one).

const k = 1.380_648_52e-23*(J/K) # (79) Boltzmann constant
const Na = 6.022_140_76e23/mol # exact, Avogadro constant
const k = 1.380_649e-23*(J/K) # exact, Boltzmann constant
const R = Na*k # molar gas constant
Copy link
Contributor

Choose a reason for hiding this comment

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

🎉

@ajkeller34
Copy link
Collaborator

I think for now the correct thing to do would be to merge this and discuss in a dedicated issue if it makes sense for Unitful.jl to have both new and old versions of CODATA, when PhysicalConstants.jl exists and fills that role nicely already. This might be a bit radical but perhaps Unitful should not define any constants, given that PhysicalConstants does the job so well...?

@ajkeller34 ajkeller34 merged commit 584d50d into PainterQubits:master Jun 17, 2019
@c42f
Copy link
Contributor

c42f commented Jun 17, 2019

I think having the latest CODATA values used by default is highly desirable 👍

It would be possible to allow swapping out values to use different CODATA releases but you need a layer of indirection. Actually PhysicalConstants already provides most of the abstraction you need as a PhysicalConstant is a unique type for each constant and that separates the identity of the constant from the current best measured value.

The types for the constants can be defined within PhysicalConstants, while the conversion from those types to float/big/etc values can be defined separately. So you'd only have one type for, eg, PhysicalConstants.G rather than unique types PhysicalConstants.CODATA2014.G and PhysicalConstants.CODATA2018.G.

In the simplest case the definitions of the values would be in a set of CODATA modules, only one of which could be loaded at a given time. Roughly speaking these would contain definitions such as

Base.float(::typeof(PhysicalConstants.G)) = 6.6743e-11u"m^3*kg^-1*s^-2"

However, dynamically choosing a different CODATA module isn't really natural in this setup and it's not clear how a default would work. Also this would imply a global choice of CODATA across all loaded modules within the julia session (that might arguably be a good thing).

As another similar global option, you could have a function to force eval of definitions like the Base.float definition to force older CODATA into the current session. I'd argue that this might make the most sense because you can default to the latest, but for testing could revert to older CODATA for testing. As an ugly sketch of this kind of monkey patching:

julia> load_codata2014() = eval(:(Base.float(::typeof(PhysicalConstants.CODATA2018.G)) = 6.67408e-11u"m^3*kg^-1*s^-2"))
load_codata2014 (generic function with 1 method)

julia> PhysicalConstants.CODATA2018.G
Newtonian constant of gravitation (G)
Value                         = 6.6743e-11 m^3 kg^-1 s^-2
Standard uncertainty          = 1.5e-15 m^3 kg^-1 s^-2
Relative standard uncertainty = 2.2e-5
Reference                     = CODATA 2018

julia> load_codata2014()

julia> PhysicalConstants.CODATA2018.G
Newtonian constant of gravitation (G)
Value                         = 6.67408e-11 m^3 kg^-1 s^-2
Standard uncertainty          = 1.5e-15 m^3 kg^-1 s^-2
Relative standard uncertainty = 2.2e-5
Reference                     = CODATA 2018

In this sketch, just pretend that I'm monkey patching float for PhysicalConstants.G rather than PhysicalConstants.CODATA2018.G. Done this way, any functions which rely on converting G to a float should be recompiled correctly. It's ugly, but I think if you're happy with the choice of CODATA being global to the julia session and you only want the older versions for testing it's a reasonable way to go.

@giordano
Copy link
Collaborator

I agree that for the time being the best thing to do is to just update the constants.

About integrating functionalities with PhysicalConstants.jl we should move to a new issue. I'll just point out that PhysicalConstants.jl depends on Unitful.jl, so we'd need to factor out a base package that both packages can depend on.

@sostock
Copy link
Collaborator Author

sostock commented Jun 17, 2019

This might be a bit radical but perhaps Unitful should not define any constants, given that PhysicalConstants does the job so well...?

I would be fine with removing all constants from Unitful in favor of PhysicalConstants, if it would be just as easy to use as the current Unitful version, which I think would not require much work.

If Unitful removed all constants and PhysicalConstants would register its submodules with Unitful and add some units based on its constants (like the unified atomic mass unit), one could get the same functionality as the current Unitful, the only difference being that one would have to do using Unitful, PhysicalConstants.CODATA2018 instead of just using Unitful.

I wouldn’t mind having to choose a dataset (in this case CODATA2018) explicitly. I actually think it’s good to remind the user that the values of some constants/units are only fixed within a specific dataset.

@c42f
Copy link
Contributor

c42f commented Jun 18, 2019

Certainly I think it'd be great it Unitful defer to PhysicalConstants to keep CODATA up to date.

However, I think having to choose the particular version of CODATA will be rather bad for usability. Will choice of CODATA be a per-module or global decision? If per-module, how will units relying on different versions of CODATA interact? If global, a module which uses Unitful will not be usable without loading CODATA separately (the module itself cannot load a particular CODATA or it will clash with other modules which load a different one).

I'd much prefer a solution where Unitful always uses the latest by default (as does PhysicalConstants), but a previous version of the standard can be globally installed for testing purposes.

@giordano
Copy link
Collaborator

I'd much prefer a solution where Unitful always uses the latest by default (as does PhysicalConstants)

Actually

using PhysicalConstants

doesn't load any dataset at all. Users have always to explicitly load the desired dataset, e.g., PhysicalConstants.CODATA2014 or PhysicalConstants.CODATA2018.

@c42f
Copy link
Contributor

c42f commented Jun 18, 2019

as does PhysicalConstants

Sorry, poor wording on my part - I didn't mean to imply anything about what PhysicalConstants does right now.

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