PainterQubits / Unitful.jl

Physical quantities with arbitrary units
Other
612 stars 112 forks source link

Add consistent CGS unit system #424

Open Gregstrq opened 3 years ago

Gregstrq commented 3 years ago

First of all, I would like to thank the creators of the package. It is very powerful: one can add all sorts of units by expressing them in terms of SI units. This way, some CGS units were already added in issue #395.

However, I should point out that varying units is not the only difference between the two unit systems. They also differ in how the base dimensions and derived dimensions are defined. (Of course, it is true only for electromagnetic quantities.) So, if one plugs CGS units into CGS equations, but CGS units are expressed in terms of SI units, the dimension of the answer is nonsensical.

So, in order to work with CGS units consistently, one needs to correctly define base and derived dimensions. The good news is, as far as I understand, one does not need to rewrite everything to incorporate such changes; one only needs to rewrite the file pkgdefaults.jl.

Since the form of equations involving electromagnetic quantities are different in SI and CGS systems, one never mixes both types of units in the calculation: the quantities are first converted to a single preferred system, and only then are plugged into equations. The conversion part should be easily handled by the units definitions (we can define CGS units in terms of SI units, but we can also do the reverse thing). Because of this, there is, actually, no point to bother too much about the transformations of quantities between the two unit systems. A user would choose the unit system when the package is loaded, and then he/she would stick with it.

Gregstrq commented 3 years ago

The way I see it, one just needs to add an alternative pkgdefaults file and provide an interface to choose the needed one. What do you think about this idea?

I am ready to write an alternative pkgdefaults file myself, however, the interface part needs discussion. It seems that switching of the unit system at runtime implies deletion of all stored dimensions, derived_dimensions and units, followed by running the alternative pkgdefaults file, but I do not know the structure of the library enough to implement that.

Alternatively, different pkgdefaults may be provided as different packages. In this regards, I would like to point to the issue #359. As suggested there, everything besides the pkgdefaults.jl file can be separated into UnitfulBase.jl. Then, Unitful.jl would reexport UnitfulBase.jl and load up the currently existing pkdefaults file for SI unit system. This way, there should be no breaking changes for the users of Unitful.jl. In a similar manner, one can create UnitfulGauss.jl, which will reexport UnitfulBase.jl as well but will use a pkgdefaults file for Gauss CGS unit system instead.

rafaqz commented 3 years ago

This sounds reasonable to me. UnitfulBase.jl and Unitful.jl could both be in this repository, minimizing the maintenance overhead, sharing docs, etc. UnitfulBase.jl would be a subdirectory.

Gregstrq commented 3 years ago

This sounds reasonable to me. UnitfulBase.jl and Unitful.jl could both be in this repository, minimizing the maintenance overhead, sharing docs, etc. UnitfulBase.jl would be a subdirectory.

If UnitfulBase is a subdirectory, is it possible to import only it without importing the whole Unitful? I see that subdirectories can be registered separately from main repos. How are subdirectories supposed to be organized? Should each of the subdirectories have the usual package structure inside?

There is also a question about how to reregister Unitful so that it points to a subdirectory in the repository.

rafaqz commented 3 years ago

It can be wherever we like. Its just a regular package structure in a subdir. You can register with At_JuliaRegistrator register subdir=UnitfulBase.jl (or similar) .

But see what people think! - this is a major change and Im a very occasional contributor here, Im just pointing out that its not too much overhead now for ongoing maintenance.

JuliaRegistrator commented 3 years ago

Error while trying to register: Register Failed @rafaqz, it looks like you are not a publicly listed member/owner in the parent organization (PainterQubits). If you are a member/owner, you will need to change your membership to public. See GitHub Help

rafaqz commented 3 years ago

Sorry I forgot it doesnt recognize code blocks...

Gregstrq commented 3 years ago

By the way, can you tell me who are the main maintainers (decision makers) of the package?

ajkeller34 commented 3 years ago

I chime in occasionally if I have a strong opinion on something, but that is infrequent and I haven't had much bandwidth to contribute in a while. @giordano does a much better job of maintaining than myself and deserves a lot of credit.

For what it's worth, I like the proposal for UnitfulBase and Unitful. I've had mostly good experiences with the subdir feature of Pkg but I think it is newer and don't remember in which version it was introduced.

Gregstrq commented 3 years ago

I have asked about supported Julia versions on discourse. The answer I got is here.

The gist of it: one should be able to use subdirectory packages with any Julia 1.x version, although finer support of all Pkg features (like dev) may be lacking for x<5.

m-wells commented 3 years ago

I like the idea of UnitfulBase. However, it seems to me that it would be impossible to use UnitfulGauss and Unitful (the SI defaults) together as they would have overriding unit definitions. Perhaps this isn't a big deal but I can imagine a few use cases (like converting between SI and CGS) where this would be an issue. Another (less idea) solution would be to go the route of UnitfulUS.jl and suffix everything with cgs to avoid namespace conflicts. Although at that point you wouldn't need to breakout UnitfulBase

Gregstrq commented 3 years ago

Currently, pkgdefaults file defines CGS units in terms of SI units. Correspondingly, pkgdefaults file of UnitfulGauss would also define SI units in terms of CGS units. These definitions should handle the conversions if one needs them.

The thing is, we should separate units and dimension systems. Irrespective of the dimension system, SI and CGS units can be converted into each other without any problem. However, SI and Gauss dimension systems are different: in Gauss system, Amper is not the base dimension, it is expressed in terms of "cm", "g" and "s". This change affects only the dimensions of all units in the field of electromagnetism however, there is no change in the dimensions of the mechanical units.

I can not imagine a case where one would mix different dimension systems: the form of Maxwell equations in SI and Gauss is a bit different. Thus, in the applications, one usually sticks with the dimension system of choice. One can still convert the units though, but it happens without the change of dimension system.

Gregstrq commented 3 years ago

To illustrate the separation of units and dimension systems, consider the following example.

In current pkgdefaults, there is a separate dimension for temperature. However, we can decide to put boltzmann constant to unity and measure the temperature in energy units. At the same time, we can still define the units of Kelvin. We just say that 1K = (k_b) Joules (here, k_b is boltzmann constant in SI).

We can also put the speed of light to unity and measure mass in units of energy. At the same time we can still define units of gramms in terms of the corresponding rest energy (mc^2).

m-wells commented 3 years ago

My point is there will be a name space conflict if you want to have a CGS gram g be defined in terms of rest energy (such as MeV) and a SI gram g. This means that importing Unitful (the SI defaults) would try to override the already defined g. This is only an issue if you ever wanted to use the two packages at the same time.

Multiple definitions for the same unit will prohibit the packages from being used together. For most use cases this is probably a nonissue.

giordano commented 3 years ago

To avoid similar issues, in PhysicalConstants.jl I decided that loading the main package would not load any constant into scope. Constants are actually defined in different submodules corresponding to different datasets (at the moment only different CODATA versions) and the user needs to load them explicitly to bring them into scope.

m-wells commented 3 years ago

How would theu"" macro work in the case of multiple units registered with the same name?

Gregstrq commented 3 years ago

Multiple definitions for the same unit will prohibit the packages from being used together. For most use cases this is probably a nonissue.

That is true that it would be impossible to use two packages at the same time. However, I should point out that I can not imagine even a single case where we would need it (of course, it does not prove that there is none).

To avoid similar issues, in PhysicalConstants.jl I decided that loading the main package would not load any constant into scope. Constants are actually defined in different submodules corresponding to different datasets (at the moment only different CODATA versions) and the user needs to load them explicitly to bring them into scope.

The problem in our case is the conflict of @u_str names between different unit systems. Separation of UnitfulBase and Unitful solves this problem.

Gregstrq commented 3 years ago

To avoid similar issues, in PhysicalConstants.jl I decided that loading the main package would not load any constant into scope. Constants are actually defined in different submodules corresponding to different datasets (at the moment only different CODATA versions) and the user needs to load them explicitly to bring them into scope.

How would theu"" macro work in the case of multiple units registered with the same name?

Actually, there might be a way to do everything with modules. The way @u_str is defined, it operates with array unitmods which by default always contains Unitful. If we have different unit systems defined in different submodules, we could replace default unitmods array with unitmods array that points to the correct submodule.

May be we can define some global variable unitmod_default which is used inside @u_str, and which by defaults points to the SI submodule. Then, we can provide the users with functions si() and gauss() which would change unitmod_default so that it points to the correct submodule.

Still, there is benefit in separation of UnitfulBase and Unitful. May be the user does not want to use neither SI nor Gauss unit system. Then, he/she can define own unit system on base of UnitfulBase without downloading predefined unit systems.

sostock commented 3 years ago

UnitfulGauss could also provide its own string macro (maybe @cgs_str instead of @u_str?) to avoid name conflicts.

Gregstrq commented 3 years ago

UnitfulGauss could also provide its own string macro (maybe @cgs_str instead of @u_str?) to avoid name conflicts.

Is it really convenient for the users?

Also, the users potentially might want to define some new unit systems which are alternative both to SI and to Gauss. Then, they would have to create a new string macro each time they add a new unit system?

There are also packages that built upon Unitful. If Gauss unit system uses the same @u_str macro, it is easier to adapt all those packages to work with Gauss unit system as well. Or adapt to work with other potential alternative unit systems.

m-wells commented 3 years ago

There are also packages that built upon Unitful. If Gauss unit system uses the same @u_str macro, it is easier to adapt all those packages to work with Gauss unit system as well. Or adapt to work with other potential alternative unit systems.

UnitfulAstro.jl is an excellent example where someone might want to use CGS (for working with units like ergs).

Gregstrq commented 3 years ago

I have created a WIP PR which splits UnitfulBase into a subdirectory. The CI appears broken because Unitful depends on UnitfulBase which is not a registered package yet. However, I made sure that the tests run successfully on my computer (locally, one can dev UnitfulBase in the project environment of Unitful).

Gregstrq commented 3 years ago

Could anyone of the maintainers look at the PR I have created and tell me if there is any interest in working on it? If there is no interest whatsoever, I would like to hear that as soon as possible, no offense taken.

In case there is interest, I am eager to revise the PR, but for that I need to receive some kind of feedback first.