Source code for constructterms.field
from copy import deepcopy
[docs]class Field:
"""
Mathematically this object is a representation charged under some symmetry groups.
Physically it is a field of the theory.
:param name: The name of the field / representation
:type name: str
:param charges: The charges / irreps under the Groups. Has the form :code:`{Group1: charge1, Group2: charge2}`,
where :code:`Group1` and :code:`Group2` have to be an Object of the :py:meth:`~constructterms.group.Group`
class.
Note that Abelian groups have integer charges, U(1) groups have integer or float charges and non-Abelian groups
have a list of one or more irreps, e.g.::
charges = {Abelian_Group: 2, U1_Group: 0.5, Non_Abelian_Group: ['3_1','3_2']}
:type charges: dict, optional
:param components: The single components of a field. E.g. if the field is a '3' representation under A4,
it would be::
components = {A4: {'3': [['x1', 'x2', 'x3']]}}
:type components: dict, optional
"""
def __init__(self, name, charges=None, components=None):
if charges is None:
charges = {}
if components is None:
components = {}
self.name = name
self.charges = charges
self.components = components
def __repr__(self):
return self.name
[docs] def copy(self):
"""
Returns a deep copy.
"""
return deepcopy(self)
[docs] def times(self, other_field):
"""
Calculates the tensor product of 'self' and 'other_field'.
:param other_field: The other field that you want to multiply this field with.
:type other_field: :py:meth:`~constructterms.field.Field`
:return: A field that represents the tensor product of 'self' and 'other_field'.
:rtype: :py:meth:`~constructterms.field.Field`
"""
# Do tensor products
if self.charges.keys() != other_field.charges.keys():
raise KeyError('''The Field that you are multiplying with is not charged under the same symmetries!
Make sure that both fields have the same symmetries in the 'charges'-dictionary!''')
new_charges = {group: group.make_product(self.charges[group], other_field.charges[group])
for group in self.charges}
# Calculate components with Clebsch-Gordans
if self.components.keys() != other_field.components.keys():
raise KeyError('''The Field that you are multiplying with does not have components under the same
symmetries! Make sure that both fields have the same symmetries in the 'charges'-dictionary!
''')
new_components = {group: group.make_product_components(self.components[group], other_field.components[group])
for group in self.components}
# Return result
return Field(self.name + ' ' + other_field.name, charges=new_charges, components=new_components)
[docs] def is_desired(self, desired_field, print_cause=False, ignore=None) -> bool:
"""
Check if 'self' is charged in the same way as 'desired_field' under all symmetries. For non-Abelian symmetries
it checks, if 'self' contains at least one of the irreps of 'desired_field'. Use this for example to check if
a Lagrangian-term is invariant.
:param desired_field: Compare the charges of 'self' to this field. Has to be an instance of the Field class!
:type desired_field: :py:meth:`~constructterms.field.Field`
:param ignore: List here any symmetry that you do not want to compare to the desired field.
:type ignore: list, optional
:param print_cause: If 'True' it prints which symmetry is causing the end-result to be 'False'
:type print_cause: bool, optional
:return: True or False
:rtype: bool
"""
if ignore is None:
ignore = []
if self.charges.keys() != desired_field.charges.keys():
raise KeyError('''The Field that you are comparing with is not charged under the same symmetries! Make sure
that both fields have the same symmetries in the 'charges'-dictionary!''')
result = all([group.is_desired(self.charges[group], desired_field.charges[group])
for group in self.charges if group not in ignore])
if print_cause is True and result is False:
for group in self.charges:
if group not in ignore:
if not group.is_desired(self.charges[group], desired_field.charges[group]):
print('The charge/irreps of your field under the group '+group.name+' is not the desired one')
return result