def tf_A123(self, t_T, want_A1=True, want_A2=True, want_A3=True): """See base class.""" t_A1 = t_A2 = t_A3 = None if want_A1: t_A1 = mu.tfc128(-4 / 21) * tf.einsum('mijm->ij', t_T) if want_A2 or want_A3: t_A2 = mu.tfc128(-4 / (3 * 3)) * ( # Antisymmetrize in last 3 indices, but using antisymmetry in last 2. # Note factor 1/3 above (in -4/(3*3) rather than -4/3). t_T + tf.einsum('lijk->ljki', t_T) + tf.einsum('lijk->lkij', t_T)) if want_A3: t_A3 = a123.tf_A3_from_A2(t_A2) return t_A1, t_A2, t_A3
def tf_A123(self, t_T, want_A1=True, want_A2=True, want_A3=True): t_A1, t_A2, t_A3 = None, None, None if want_A1: t_A1 = tf.einsum('mijm->ij', t_T) * mu.tfc128(-4.0 / 21) # TODO(tfish): Do check if the SO(8)-origin-A1 is actually diag([1.0]*8) # or perhaps now has an extra factor 1j. if want_A2 or want_A3: # Over-satisfying is OK: When asked for A3 only, we also compute A2. t_A2 = mu.tfc128(-4.0 / (3 * 3)) * (t_T + tf.einsum('lijk->ljki', t_T) + tf.einsum('lijk->lkij', t_T)) if want_A3: t_A3 = a123.tf_A3_from_A2(t_A2) return t_A1, t_A2, t_A3
def __init__( self, Theta, e7=e7, verbose=False, check_gaugeability=True, gaugeability_atol=1e-8, # Either `None`, or ('SUSY', None), # or ('M2G', {[8]-sequence of masses}). stationarity_tweak=None): super().__init__(e7.t56r, verbose=verbose) if check_gaugeability: if get_gaugeability_condition_violations(Theta, e7=e7, atol=gaugeability_atol): raise ValueError('Non-gaugeable Theta-tensor provided.') self._stationarity_tweak = stationarity_tweak self._opt_tc_stationarity_tweak = ( None if stationarity_tweak is None or stationarity_tweak[1] is None else mu.tff64(stationarity_tweak[1])) self._tc_X = tc_X = mu.tff64(get_X(Theta, e7=e7)) self._tc_XX = tf.einsum('MNQ,PQN->MP', tc_X, tc_X) self._tc_e7_S_rc = tf.constant(e7.S_rc, dtype=tf.complex128) self._tc_1j = mu.tfc128(0, 1) self._tc_28_8_8 = tf.constant(algebra.g.su8.m_28_8_8, dtype=tf.complex128) self._tc_56_888 = tf.constant(algebra.g.su8.m_56_8_8_8, dtype=tf.complex128) self._tc_eps_56_56_8_8 = tf.constant(algebra.g.su8.eps_56_56_8_8, dtype=tf.complex128) self._tc_omega = tf.constant(e7.omega, dtype=tf.complex128)
def tf_fermion_massmatrix(t_A3, t_potential, tc_masses_factor): """Computes the spin-1/2 mass matrix from the A3-tensor.""" # The extra factor 2.0 relative to https://arxiv.org/abs/1906.00207 # makes the fermion masses align with the way particle states are # grouped into SUSY multiplets in appendix (B.2) of: # https://arxiv.org/abs/1909.10969 return mu.tfc128(2.0) * tf.einsum('ij,ik->jk', t_A3, tf.math.conj( t_A3)) * (tc_masses_factor / tf.cast(t_potential, tf.complex128))
def tf_T(self, t_vielbein): # Here, we do not actually compute the full T-tensor, but the T_i^jkl part. # This is all that we ever need here. V56_RC = tf.einsum('RS,SC->RC', tf.cast(t_vielbein, tf.complex128), self._tc_e7_S_rc) t_Q_Mijkl = self._tc_1j * tf.einsum( 'NP,NI,Iij,MPQ,QK,Kkl->Mijkl', self._tc_omega, V56_RC[:, 28:], self._tc_28_8_8, tf.cast( self._tc_X, tf.complex128), V56_RC[:, :28], self._tc_28_8_8) t_Q_Mij = tf.einsum('Mijil->Mjl', t_Q_Mijkl) * mu.tfc128(-2 / 3.0) return mu.tfc128(0.0, 0.75 / 2**.5) * tf.einsum( # Note fudge-factor sqrt(2) above. # This makes the T-tensor match the colab notebook on SO(8) gauging. 'MN,Mkl,NI,Iij->klij', self._tc_omega, t_Q_Mij, V56_RC[:, :28], self._tc_28_8_8)
def tf_A3_from_A2(t_A2): """Computes the A3-tensor from the A2-tensor.""" tc_56_8_8_8 = tf.constant(algebra.g.su8.m_56_8_8_8.astype( numpy.complex128), dtype=tf.complex128) tc_eps_56_56_8_8 = tf.constant(algebra.g.su8.eps_56_56_8_8.astype( numpy.complex128), dtype=tf.complex128) t_A2_nP = tf.einsum('nijk,Pijk->nP', tf.math.conj(t_A2), tc_56_8_8_8) return tf.einsum('nP,APlm,Blmn->AB', t_A2_nP, tc_eps_56_56_8_8, tc_56_8_8_8) * mu.tfc128(2**.5 / 24.0)
def tf_vector_massmatrix(t_A2, t_potential, tc_masses_factor): """Computes the spin-1 mass matrix from the A2-tensor.""" # This is most readily available in https://arxiv.org/pdf/1103.2785.pdf, # Eq. (5.27) and (5.28), setting the scaling-symmetry ('trombone') # contributions B to zero. # With the conventions from arXiv:1103.2785, we reproduce # Table B.3 of arXiv:1909.10969. # Note that we get 56 masses, 28 of which are spurious and will always be zero # in any valid gauging. tc_56_8_8_8 = tf.constant(algebra.g.su8.m_56_8_8_8.astype( numpy.complex128), dtype=tf.complex128) tc_28_8_8 = tf.constant(algebra.g.su8.m_28_8_8.astype(numpy.complex128), dtype=tf.complex128) tc_eps_56_56_8_8 = tf.constant(algebra.g.su8.eps_56_56_8_8.astype( numpy.complex128), dtype=tf.complex128) t_A2_8_56 = mu.tfc128(1 / 6.0) * tf.einsum('ipqr,Xpqr->iX', t_A2, tc_56_8_8_8) t_A2c_8_56 = tf.math.conj(t_A2_8_56) M_ij_KL = ( mu.tfc128(-1 / 4.0) * tf.einsum('iX,lX,jk,Iij,Kkl->IK', t_A2_8_56, t_A2c_8_56, tf.eye(8, dtype=tf.complex128), tc_28_8_8, tc_28_8_8) + mu.tfc128(1 / 8.0) * tf.einsum('ipqk,ljpq,Iij,Kkl->IK', t_A2, tf.math.conj(t_A2), tc_28_8_8, tc_28_8_8)) M_ijkl = mu.tfc128( 1 / 4.0) * tf.einsum('iX,lY,XYjk,Iij,Kkl->IK', t_A2_8_56, t_A2_8_56, tc_eps_56_56_8_8, tc_28_8_8, tc_28_8_8) M_vec = tf.reshape( tf.einsum( 'abAB->aAbB', tf.reshape( tf.stack([ M_ij_KL, M_ijkl, tf.math.conj(M_ijkl), tf.math.conj(M_ij_KL) ]), [2, 2, 28, 28])), [56, 56]) return (M_vec * tc_masses_factor / tf.cast(t_potential, tf.complex128))
def tf_dwn_stationarity_vec(t_A1, t_A2): """Computes stationarity-violation 70-vector 'in the local frame'.""" # Formula: # arXiv: https://arxiv.org/pdf/1302.6219.pdf, formula (3.2); # originally: https://inspirehep.net/literature/191530 # (2.20) - (2.22). _m_8888sd_35ortho, _m_8888asd_35ortho = _get_35sd_asd_bases() t_x0 = (tf.einsum('mi,mjkl->ijkl', t_A1, t_A2) + mu.tfc128(-0.75, 0.0) * tf.einsum('mnij,nklm->ijkl', t_A2, t_A2)) t_x0_real = tf.math.real(t_x0) t_x0_imag = tf.math.imag(t_x0) # The self-dual part must be zero. t_x0_re_sd = tf.einsum('ijkl,ijklX->X', t_x0_real, mu.tff64(_m_8888sd_35ortho)) t_x0_im_asd = tf.einsum('ijkl,ijklX->X', t_x0_imag, mu.tff64(_m_8888asd_35ortho)) return tf.concat([t_x0_re_sd, t_x0_im_asd], axis=0)
def tf_vector_massmatrix(self, ts_A123, t_potential): """See base class.""" _, t_A2, _ = ts_A123 return a123.tf_vector_massmatrix( t_A2, t_potential, mu.tfc128(-self.signature.vector_masses_factor))
def tf_fermion_massmatrix(self, ts_A123, t_potential): """See base class.""" *_, t_A3 = ts_A123 return a123.tf_fermion_massmatrix( t_A3, t_potential, mu.tfc128(-self.signature.fermion_masses_factor))