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

Convert from energy to velocity in relativistic formulary #1056

Closed
sfeister opened this issue Mar 4, 2021 · 19 comments · Fixed by #1540 · May be fixed by #1297
Closed

Convert from energy to velocity in relativistic formulary #1056

sfeister opened this issue Mar 4, 2021 · 19 comments · Fixed by #1540 · May be fixed by #1297
Assignees
Labels
plasmapy.formulary Related to the plasmapy.formulary subpackage

Comments

@sfeister
Copy link

sfeister commented Mar 4, 2021

Feature request

I can't find a good function in either plasmapy or astropy to convert from kinetic energy into relativistic velocity for a single particle. If it doesn't exist, I'm happy to add it to the relativistic formulary.

@pheuer pheuer self-assigned this Mar 4, 2021
@pheuer
Copy link
Member

pheuer commented Mar 4, 2021

If this function doesn't exist somewhere I've overlooked I'm happy to help @phyzicist add this. This function would be a convenient refactor of these lines in diagnostics.proton_radiography.SyntheticProtonRadiograph:

# Calculate the velocity corresponding to the proton energy
ER = self.proton_energy * 1.6e-19 / (self.m * self._c ** 2)
v0 = self._c * np.sqrt(1 - 1 / (ER + 1) ** 2)

@sfeister
Copy link
Author

sfeister commented Mar 4, 2021

I propose adding a function:

relativistic_velocity(m, E, kinetic=False) | (default) Calculate the velocity (in meters/second) of an object with rest mass m and total relativistic energy E.
relativistic_velocity(m, E, kinetic=True) | Calculate the velocity (in meters/second) of an object with rest mass m and kinetic energy E.

And then the contents of this function would be basically what @pheuer has already written.

@sfeister
Copy link
Author

sfeister commented Mar 4, 2021

I could also see this being articulated as an equivalency between velocity and energy

@StanczakDominik
Copy link
Member

Relativistic_velocity with an energy input sounds great and definitely more obvious than than any name with "equivalency" :)

One possible variant: speed rather than velocity? With an energy input we can't get the direction, and the way it's taught here in Poland speed implies the scalar magnitude of velocity. I don't actually know whether that distinction is common elsewhere.

@pheuer
Copy link
Member

pheuer commented Mar 5, 2021

Agreed, relativistic_speed would be better. It should probably take energy and a particle as required inputs?

@rocco8773
Copy link
Member

I propose adding a function:

relativistic_velocity(m, E, kinetic=False) | (default) Calculate the velocity (in meters/second) of an object with rest mass m and total relativistic energy E.
relativistic_velocity(m, E, kinetic=True) | Calculate the velocity (in meters/second) of an object with rest mass m and kinetic energy E.

My issue with just using relativistic_speed is that the speed could be calculated from total energy, kinetic energy, and momentum. relativistic_speed is not descriptive enough to indicate which one it is. We could possibly sidestep this if we queue off off the input units, something like...

def relativistic_speed(value: [u.J, u.kg * u.m / u.s], mass):
    # if value.unit equivalent to u.J, convert from energy
    ...

    # if value.unit equivalent to u.kg * u.m / u.s, convert from momentum
    ...

    return speed

I got to admit, I kind of like the idea of incorporating this into an astropy equivalency. However, it would be in addition to the functions defined here. The "old school" astropy equivalencies is a function that returns a list of 2-4 element tuples. A 4-element tuple is structure like (unit1, unit2, func_u1_to_u2, func_u2_to_u1). Astropy did incorporate an Equivalency class in v3.2.1 but I have not played with this class yet.

How would I see this incorporated...

from functools import partial

def relativistic(mass):
    equiv = [
        (
            u.m / u.s,
            u.J,
            partial(relativistic_energy, mass=mass),
            partial(relativistic_speed, mass=mass),
        ),
    ]
    return equiv

Then one could use it like...

>>> E = 0.7 * u.MeV
>>> speed = E.to(u.m/u.s, equivalencies=relativistic(mass=Particle("e").mass)
<Quantity 2.0489278e+08 m / s>

I did procrastinate a little and tried to construct something like this and it did work relatively well. The only issue I ran into is that the equivalencies mechanisms seemed to to strip units so I had to manually put them back in the converting functions. ...

image

@StanczakDominik
Copy link
Member

My issue with just using relativistic_speed is that the speed could be calculated from total energy, kinetic energy, and momentum. relativistic_speed is not descriptive enough to indicate which one it is.

Just jumping in before looking at that code sample to point out a potential flaw in that premise: don't most modern editors (jupyter, pycharm, ipython shell, spyder, vscode, any sufficiently advanced vim configuration) show the signature when suggesting function calls?

If this works as I think it does - and I'll try to get you some screenshots later - I think we can comfortably assume the signature to be part of the minimal information anyone will get while using the function.

@StanczakDominik
Copy link
Member

Spyder:
image

Vscode:

image

Yup, I'd say that confirms my suspicions! Without derailing the thread further, I'd say it should be fine to implement relativistic_speed as discussed, @phyzicist :)

@rocco8773
Copy link
Member

My issue with just using relativistic_speed is that the speed could be calculated from total energy, kinetic energy, and momentum. relativistic_speed is not descriptive enough to indicate which one it is.

Just jumping in before looking at that code sample to point out a potential flaw in that premise: don't most modern editors (jupyter, pycharm, ipython shell, spyder, vscode, any sufficiently advanced vim configuration) show the signature when suggesting function calls?

I see your point about about IDE's having a display of parameters info, but ...

  1. Not everyone uses (or knows) about this functionality and we should probably not make design decisions based on it.
  2. If we're adding functionality like this then we should add the whole gambit of fundamental relativistic formulae: relativistic_energy, relativistic_momentum, time_dilation, and relativistic_speed. Once that happens there's automatically an ambiguity with relativistic_speed. To avoid this ambiguity we either need to make two speed functions for calculating from energy vs momentum, or combine the functionality into one.

I'll point out my suggestion above about queuing off off of units would not work with natural units c=1, but I don't think any of our functionality works with natural units.

@StanczakDominik
Copy link
Member

Sure, but if you're aware that a function exists, you've either checked the docs, in which case you've seen either the signature or an example of usage, or you've used autocomplete, in which case you'll most likely get the pop-up anyway, no?

@rocco8773
Copy link
Member

Sure, but that does not address my second point. If we're going to add functionality that calculates speed from relativistic energy, then we should also add functionality to calculates speed from relativistic momentum. We should do this to make the pkg as complete as possible. Now, we have one of two approaches to accomplish this...

  1. combine both calculations into one relativistic_speed function
  2. split the functionality into two functions, say, relativistic_speed_from_energy and relativistic_speed_from_momentum

Now, there's pros and cons to both approaches. I think my preference would be for option 1, but, if @phyzicist wants to take on this contribution, then I'd let him decide how he'd like to approach it.

@StanczakDominik
Copy link
Member

StanczakDominik commented Mar 8, 2021

Tbh I'm fine starting as is, from energy, and adding a dispatch-on-unit mechanism later on. It'd come in handy in a bunch of places but a general implementation is likely beyond the scope of this here issue.

But a simple implementation for both momentum -> speed and energy -> speed here would also be cool to see, of course :)

Sorry, I'm a little cranky today :D

@pheuer
Copy link
Member

pheuer commented Mar 8, 2021

What was the problem with just accepting velocity, momentum, or energy as the input and then calculating appropriately based on units? Like @rocco8773 described at the very beginning? It might not be the most pythonic choice, but it gets the function to fill the roles we want with the right name. Then we can worry about refactoring it using fancy python later?

The only ambiguity would be total energy vs. kinetic energy. I'd suggest assuming kinetic energy and making that clear in the function call.

@rocco8773
Copy link
Member

rocco8773 commented Mar 8, 2021

Tbh I'm fine starting as is, from energy, and adding a dispatch-on-unit mechanism later on. It'd come in handy in a bunch of places but a general implementation is likely beyond the scope of this here issue.

I'm fine with this too. My only concern is the first part gets contributed and then the rest gets abandoned/forgotten. The first PR contributes what was actually needed, so then there would be little to no motivation to complete the overall functionality.

Sorry, I'm a little cranky today :D

No worries. It's a Monday so it's allowed. 😆

What was the problem with just accepting velocity, momentum, or energy as the input and then calculating appropriately based on units? Like @rocco8773 described at the very beginning? It might not be the most pythonic choice, but it gets the function to fill the roles we want with the right name. Then we can worry about refactoring it using fancy python later?

The only ambiguity would be total energy vs. kinetic energy. I'd suggest assuming kinetic energy and making that clear in the function call.

@StanczakDominik Correct me if I'm wrong, but I think this issue was mainly center with my suggestion involving some trickery that could be beyond the scope of the functionality originally proposed in this PR. The equivalencies part is definitely beyond the original scope and should be contributed as its own PR.

In the final functionality I would incorporate the unit interpretation and a kwarg like...

def relativistic_speed(value: [u.J, u.kg * u.m / u.s], particle: ParticleLike, from: str = None) -> u.m/u.s:
    ...
    return speed

Here the from would have options like: 'kinetic_energy' and/or 'KE', 'total_energy' and/or 'Etotal', and 'momentum' and/or 'p'. If from is None and value has units of energy, then total energy would be assumed. If there's a clash between from and the interpreted units, then an Exception would be raised. There might be cleaner ways of doing this, but this route is the first approach that comes to my mind.

@pheuer
Copy link
Member

pheuer commented Mar 8, 2021

But isn't the kinetic_energy vs. total_energy the only reason you need the from string? Otherwise units are sufficient. It seems to me that

def relativistic_speed(value: [u.J, u.kg * u.m / u.s, particle: ParticleLike) -> u.m/u.s:
    if energy units:
         momentum = expression
   return velocity(momenutm)

Works if you make clear in documentation that this takes the KINETIC energy?

@rocco8773
Copy link
Member

rocco8773 commented Mar 8, 2021

Ok, I see you're point. I think this route would be a little more concise then...

def relativistic_speed(value: [u.J, u.kg * u.m / u.s], particle: ParticleLike, is_kinetic_energy: bool = False) -> u.m/u.s:
    if value.units.is_equivalent(u.J):
        if is_kinetic_energy:
            # convert KE to momentum
            value = ...
        else:
            # convert Etotal to momentum
            value = ...

    # convert mometum to speed
    speed = ...

    return speed

@pheuer
Copy link
Member

pheuer commented Mar 8, 2021

Yes, that seems like the way to go (at least for now) to me!

@StanczakDominik
Copy link
Member

I thought functools.singledispatch could help us write that, but units are not types, so that's out of the question.

@namurphy namurphy added the plasmapy.formulary Related to the plasmapy.formulary subpackage label Jun 1, 2021
Tlord18 pushed a commit to Tlord18/PlasmaPy that referenced this issue Oct 6, 2021
)

* Add function to convert kinetic energy and total energy to relativistic speed
Tlord18 pushed a commit to Tlord18/PlasmaPy that referenced this issue Oct 6, 2021
)

* Add function to convert kinetic energy and total energy to relativistic speed
Tlord18 pushed a commit to Tlord18/PlasmaPy that referenced this issue Oct 6, 2021
)

* Add function to convert kinetic energy and total energy to relativistic speed
@pheuer pheuer linked a pull request Oct 6, 2021 that will close this issue
3 tasks
@namurphy
Copy link
Member

namurphy commented Aug 18, 2022

To come back to this after a while, in #1539 I'm creating the RelativisticBody class that accepts a particle and any of $V$, $γ$, $p$, $E_{tot}$, or $E_k$, and has attributes that will provide all of these quantities.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
plasmapy.formulary Related to the plasmapy.formulary subpackage
Projects
None yet
5 participants