Conservation rules#
Show code cell content
import attrs
import graphviz
from IPython.display import display
import qrules
from qrules.conservation_rules import (
SpinEdgeInput,
SpinNodeInput,
parity_conservation,
spin_conservation,
spin_magnitude_conservation,
)
from qrules.quantum_numbers import Parity
QRules generates MutableTransition
s, populates them with quantum numbers (edge properties representing states and nodes properties representing interactions), then checks whether the generated MutableTransition
s comply with the rules formulated in the conservation_rules
module.
The conservation_rules
module can also be used separately. In this notebook, we will illustrate this by checking spin and parity conservation.
Parity conservation#
parity_conservation(
ingoing_edge_qns=[Parity(-1)],
outgoing_edge_qns=[Parity(+1), Parity(+1)],
l_magnitude=1,
)
True
Spin conservation#
See also
spin_conservation()
, tests/unit/conservation_rules/test_spin.py
, PDG2020, §Quark Model, and these lecture notes by Curtis Meyer.
spin_conservation()
checks whether spin magnitude and spin projections are conserved. In addition, it checks whether the Clebsch-Gordan coefficients are non-zero, meaning that the coupled spins on the interaction nodes are valid as well.
No spin and angular momentum#
spin_conservation(
ingoing_spins=[
SpinEdgeInput(0, 0),
],
outgoing_spins=[
SpinEdgeInput(0, 0),
SpinEdgeInput(0, 0),
],
interaction_qns=SpinNodeInput(
l_magnitude=0, # false if 1
l_projection=0,
s_magnitude=0,
s_projection=0,
),
)
True
Non-zero example#
spin_conservation(
ingoing_spins=[
SpinEdgeInput(1, 0),
],
outgoing_spins=[
SpinEdgeInput(1, +1),
SpinEdgeInput(1, -1),
],
interaction_qns=SpinNodeInput(
l_magnitude=1,
l_projection=0,
s_magnitude=2,
s_projection=0,
),
)
True
Example with a StateTransition
#
First, generate some StateTransition
s with generate_transitions()
, then select one of them:
reaction = qrules.generate_transitions(
initial_state="J/psi(1S)",
final_state=["K0", "Sigma+", "p~"],
allowed_interaction_types="strong",
formalism="canonical",
)
transition = reaction.transitions[0]
Next, have a look at the edge and node properties, and use the underlying Topology
to extract one of the node InteractionProperties
with the surrounding states (these are tuple
s of a Particle
and a float
spin projection).
Show code cell source
dot = qrules.io.asdot(transition, render_node=True)
display(graphviz.Source(dot))
dot = qrules.io.asdot(
transition.topology,
render_node=True,
render_resonance_id=True,
render_initial_state_id=True,
)
display(graphviz.Source(dot))
We select node \((0)\), which has incoming state ID \(-1\) and outgoing state IDs \(0\) and \(3\):
topology = transition.topology
node_id = 0
in_id, *_ = topology.get_edge_ids_ingoing_to_node(node_id)
out_id1, out_id2, *_ = topology.get_edge_ids_outgoing_from_node(node_id)
incoming_state = transition.states[in_id]
outgoing_state1 = transition.states[out_id1]
outgoing_state2 = transition.states[out_id2]
interaction = transition.interactions[node_id]
spin_magnitude_conservation(
ingoing_spins=[
SpinEdgeInput(
spin_magnitude=incoming_state.particle.spin,
spin_projection=incoming_state.spin_projection,
)
],
outgoing_spins=[
SpinEdgeInput(
spin_magnitude=outgoing_state1.particle.spin,
spin_projection=outgoing_state1.spin_projection,
),
SpinEdgeInput(
spin_magnitude=outgoing_state2.particle.spin,
spin_projection=outgoing_state2.spin_projection,
),
],
interaction_qns=interaction,
)
True
Contrary to expectations, this transition does not conserve spin projection and therefore spin_conservation()
returns False
:
spin_conservation(
ingoing_spins=[
SpinEdgeInput(
spin_magnitude=incoming_state.particle.spin,
spin_projection=incoming_state.spin_projection,
)
],
outgoing_spins=[
SpinEdgeInput(
spin_magnitude=outgoing_state1.particle.spin,
spin_projection=outgoing_state1.spin_projection,
),
SpinEdgeInput(
spin_magnitude=outgoing_state2.particle.spin,
spin_projection=outgoing_state2.spin_projection,
),
],
interaction_qns=interaction,
)
False
The reason is that AmpForm formulates the HelicityModel
with the helicity formalism first and then uses a transformation to get the model in the canonical basis (see formulate_clebsch_gordan_coefficients()
). The canonical basis does not conserve helicity (taken to be State.spin_projection
).
Modifying StateTransition
s#
When checking conservation rules, you may want to modify the properties on the StateTransition
s. However, a StateTransition
is a FrozenTransition
, so it is not possible to modify its interactions
and states
. The only way around this is to create a new instance with attrs.evolve()
.
First, we get the instance (in this case one of the InteractionProperties
) and substitute its InteractionProperties.l_magnitude
:
new_interaction = attrs.evolve(transition.interactions[node_id], l_magnitude=2)
new_interaction
InteractionProperties(
l_magnitude=2,
l_projection=None,
s_magnitude=1.0,
s_projection=None,
parity_prefactor=None,
)
We then again use attrs.evolve()
to substitute the Transition.interactions
of the original StateTransition
:
new_interaction_dict = dict(transition.interactions) # make mutable
new_interaction_dict[node_id] = new_interaction
new_transition = attrs.evolve(transition, interactions=new_interaction_dict)
Show code cell source
dot = qrules.io.asdot(new_transition, render_node=True)
graphviz.Source(dot)