def _get_nhl(qes1, qes2, cls_ivfs, lmax_out, cls_ivfs_bb=None, cls_ivfs_ab=None, ret_terms=False): GG_N0 = np.zeros(lmax_out + 1, dtype=float) CC_N0 = np.zeros(lmax_out + 1, dtype=float) GC_N0 = np.zeros(lmax_out + 1, dtype=float) CG_N0 = np.zeros(lmax_out + 1, dtype=float) cls_ivfs_aa = cls_ivfs cls_ivfs_bb = cls_ivfs if cls_ivfs_bb is None else cls_ivfs_bb cls_ivfs_ab = cls_ivfs if cls_ivfs_ab is None else cls_ivfs_ab cls_ivfs_ba = cls_ivfs_ab if ret_terms: terms = [] for qe1 in qes1: cL1 = qe1.cL(np.arange(lmax_out + 1)) for qe2 in qes2: cL2 = qe2.cL(np.arange(lmax_out + 1)) si, ti, ui, vi = (qe1.leg_a.spin_in, qe1.leg_b.spin_in, qe2.leg_a.spin_in, qe2.leg_b.spin_in) so, to, uo, vo = (qe1.leg_a.spin_ou, qe1.leg_b.spin_ou, qe2.leg_a.spin_ou, qe2.leg_b.spin_ou) assert so + to >= 0 and uo + vo >= 0, (so, to, uo, vo) clsu = utils.joincls([qe1.leg_a.cl, qe2.leg_a.cl.conj(), uspin.spin_cls(si, ui, cls_ivfs_aa)]) cltv = utils.joincls([qe1.leg_b.cl, qe2.leg_b.cl.conj(), uspin.spin_cls(ti, vi, cls_ivfs_bb)]) R_sutv = utils.joincls([uspin.wignerc(clsu, cltv, so, uo, to, vo, lmax_out=lmax_out), cL1, cL2]) clsv = utils.joincls([qe1.leg_a.cl, qe2.leg_b.cl.conj(), uspin.spin_cls(si, vi, cls_ivfs_ab)]) cltu = utils.joincls([qe1.leg_b.cl, qe2.leg_a.cl.conj(), uspin.spin_cls(ti, ui, cls_ivfs_ba)]) R_sutv = R_sutv + utils.joincls([uspin.wignerc(clsv, cltu, so, vo, to, uo, lmax_out=lmax_out), cL1, cL2]) # we now need -s-t uv sgnms = (-1) ** (si + so) sgnmt = (-1) ** (ti + to) clsu = utils.joincls([sgnms * qe1.leg_a.cl.conj(), qe2.leg_a.cl.conj(), uspin.spin_cls(-si, ui, cls_ivfs_aa)]) cltv = utils.joincls([sgnmt * qe1.leg_b.cl.conj(), qe2.leg_b.cl.conj(), uspin.spin_cls(-ti, vi, cls_ivfs_bb)]) R_msmtuv = utils.joincls([uspin.wignerc(clsu, cltv, -so, uo, -to, vo, lmax_out=lmax_out), cL1, cL2]) clsv = utils.joincls([sgnms * qe1.leg_a.cl.conj(), qe2.leg_b.cl.conj(), uspin.spin_cls(-si, vi, cls_ivfs_ab)]) cltu = utils.joincls([sgnmt * qe1.leg_b.cl.conj(), qe2.leg_a.cl.conj(), uspin.spin_cls(-ti, ui, cls_ivfs_ba)]) R_msmtuv = R_msmtuv + utils.joincls([uspin.wignerc(clsv, cltu, -so, vo, -to, uo, lmax_out=lmax_out), cL1, cL2]) GG_N0 += 0.5 * R_sutv.real GG_N0 += 0.5 * (-1) ** (to + so) * R_msmtuv.real CC_N0 += 0.5 * R_sutv.real CC_N0 -= 0.5 * (-1) ** (to + so) * R_msmtuv.real GC_N0 -= 0.5 * R_sutv.imag GC_N0 -= 0.5 * (-1) ** (to + so) * R_msmtuv.imag CG_N0 += 0.5 * R_sutv.imag CG_N0 -= 0.5 * (-1) ** (to + so) * R_msmtuv.imag if ret_terms: terms += [0.5 * R_sutv, 0.5 * (-1) ** (to + so) * R_msmtuv] return (GG_N0, CC_N0, GC_N0, CG_N0) if not ret_terms else (GG_N0, CC_N0, GC_N0, CG_N0, terms)
def _get_response(qes, source, cls_cmb, fal_leg1, lmax_qlm, fal_leg2=None): fal_leg2 = fal_leg1 if fal_leg2 is None else fal_leg2 RGG = np.zeros(lmax_qlm + 1, dtype=float) RCC = np.zeros(lmax_qlm + 1, dtype=float) RGC = np.zeros(lmax_qlm + 1, dtype=float) RCG = np.zeros(lmax_qlm + 1, dtype=float) Ls = np.arange(lmax_qlm + 1, dtype=int) for qe in qes: si, ti = (qe.leg_a.spin_in, qe.leg_b.spin_in) so, to = (qe.leg_a.spin_ou, qe.leg_b.spin_ou) for s2 in ([0, -2, 2]): FA = uspin.get_spin_matrix(si, s2, fal_leg1) if np.any(FA): for t2 in ([0, -2, 2]): FB = uspin.get_spin_matrix(ti, t2, fal_leg2) if np.any(FB): rW_st, prW_st, mrW_st, s_cL_st = get_covresp(source, -s2, t2, cls_cmb, len(FB) - 1) clA = ut.joincls([qe.leg_a.cl, FA]) clB = ut.joincls([qe.leg_b.cl, FB, mrW_st.conj()]) Rpr_st = uspin.wignerc(clA, clB, so, s2, to, -s2 + rW_st, lmax_out=lmax_qlm) * s_cL_st(Ls) rW_ts, prW_ts, mrW_ts, s_cL_ts = get_covresp(source, -t2, s2, cls_cmb, len(FA) - 1) clA = ut.joincls([qe.leg_a.cl, FA, mrW_ts.conj()]) clB = ut.joincls([qe.leg_b.cl, FB]) Rpr_st = Rpr_st + uspin.wignerc(clA, clB, so, -t2 + rW_ts, to, t2, lmax_out=lmax_qlm) * s_cL_ts(Ls) assert rW_st == rW_ts and rW_st >= 0, (rW_st, rW_ts) if rW_st > 0: clA = ut.joincls([qe.leg_a.cl, FA]) clB = ut.joincls([qe.leg_b.cl, FB, prW_st.conj()]) Rmr_st = uspin.wignerc(clA, clB, so, s2, to, -s2 - rW_st, lmax_out=lmax_qlm) * s_cL_st(Ls) clA = ut.joincls([qe.leg_a.cl, FA, prW_ts.conj()]) clB = ut.joincls([qe.leg_b.cl, FB]) Rmr_st = Rmr_st + uspin.wignerc(clA, clB, so, -t2 - rW_ts, to, t2, lmax_out=lmax_qlm) * s_cL_ts(Ls) else: Rmr_st = Rpr_st prefac = qe.cL(Ls) RGG += prefac * ( Rpr_st.real + Rmr_st.real * (-1) ** rW_st) RCC += prefac * ( Rpr_st.real - Rmr_st.real * (-1) ** rW_st) RGC += prefac * (-Rpr_st.imag + Rmr_st.imag * (-1) ** rW_st) RCG += prefac * ( Rpr_st.imag + Rmr_st.imag * (-1) ** rW_st) return RGG, RCC, RGC, RCG
def get_mf_resp(qe_key, cls_cmb, cls_ivfs, lmax_qe, lmax_out): """Deflection-induced mean-field response calculation. See Carron & Lewis 2019 in prep. """ # This version looks stable enough assert qe_key in ['p_p', 'ptt'], qe_key GL = np.zeros(lmax_out + 1, dtype=float) CL = np.zeros(lmax_out + 1, dtype=float) if qe_key == 'ptt': lmax_cmb = len(cls_cmb['tt']) - 1 spins = [0] elif qe_key == 'p_p': lmax_cmb = min(len(cls_cmb['ee']) - 1, len(cls_cmb['bb'] - 1)) spins = [-2, 2] elif qe_key == 'p': lmax_cmb = min(len(cls_cmb['ee']) - 1, len(cls_cmb['bb']) - 1, len(cls_cmb['tt']) - 1, len(cls_cmb['te']) - 1) spins = [0, -2, 2] else: assert 0, qe_key + ' not implemented' assert lmax_qe <= lmax_cmb if qe_key == 'ptt': cl_cmbtoticmb = {'tt': cls_cmb['tt'][:lmax_qe + 1] ** 2 * cls_ivfs['tt'][:lmax_qe + 1]} cl_cmbtoti = {'tt': cls_cmb['tt'][:lmax_qe + 1] * cls_ivfs['tt'][:lmax_qe + 1]} elif qe_key == 'p_p': cl_cmbtoticmb = {'ee': cls_cmb['ee'][:lmax_qe + 1] ** 2 * cls_ivfs['ee'][:lmax_qe + 1], 'bb': cls_cmb['bb'][:lmax_qe + 1] ** 2 * cls_ivfs['bb'][:lmax_qe + 1]} cl_cmbtoti = {'ee': cls_cmb['ee'][:lmax_qe + 1] * cls_ivfs['ee'][:lmax_qe + 1], 'bb': cls_cmb['bb'][:lmax_qe + 1] * cls_ivfs['bb'][:lmax_qe + 1]} else: assert 0, 'not implemented' # Build remaining fisher term II: FisherGII = np.zeros(lmax_out + 1, dtype=float) FisherCII = np.zeros(lmax_out + 1, dtype=float) for s1 in spins: for s2 in spins: cl1 = uspin.spin_cls(s1, s2, cls_ivfs)[:lmax_qe + 1] * (0.5 ** (s1 != 0) * 0.5 ** (s2 != 0)) # These 1/2 factor from the factor 1/2 in each B of B Covi B^dagger, where B maps spin-fields to T E B. cl2 = np.copy(uspin.spin_cls(s2, s1, cls_cmb)[:lmax_cmb + 1]) cl2[:lmax_qe + 1] -= uspin.spin_cls(s2, s1, cl_cmbtoticmb)[:lmax_qe + 1] if np.any(cl1) and np.any(cl2): for a in [-1, 1]: ai = uspin.get_spin_lower(s2, lmax_cmb) if a == - 1 else uspin.get_spin_raise(s2, lmax_cmb) for b in [1]: # a, b symmetry aj = uspin.get_spin_lower(-s1, lmax_cmb) if b == 1 else uspin.get_spin_raise(-s1, lmax_cmb) hL = 2 * (-1) ** (s1 + s2) * uspin.wignerc(cl1, cl2 * ai * aj, s2, s1, -s2 - a, -s1 - b, lmax_out=lmax_out) GL += (- a * b) * hL CL += (-1) * hL # Build remaining Fisher term II: for s1 in spins: for s2 in spins: cl1 = uspin.spin_cls(s2, s1, cl_cmbtoti)[:lmax_qe + 1] * (0.5 ** (s1 != 0)) cl2 = uspin.spin_cls(s1, s2, cl_cmbtoti)[:lmax_qe + 1] * (0.5 ** (s2 != 0)) if np.any(cl1) and np.any(cl2): for a in [-1, 1]: ai = uspin.get_spin_lower(s2, lmax_qe) if a == -1 else uspin.get_spin_raise(s2, lmax_qe) for b in [1]: aj = uspin.get_spin_lower(s1, lmax_qe) if b == 1 else uspin.get_spin_raise(s1, lmax_qe) hL = 2 * (-1) ** (s1 + s2) * uspin.wignerc(cl1 * ai, cl2 * aj, -s2 - a, -s1, s2, s1 - b, lmax_out=lmax_out) FisherGII += (- a * b) * hL FisherCII += (-1) * hL GL -= FisherGII CL -= FisherCII print("CL[1] ",CL[1]) print("GL[1] (before subtraction) ", GL[1]) print("GL[1] (after subtraction) ", GL[1] - CL[1]) GL -= CL[1] CL -= CL[1] GL *= 0.25 * np.arange(lmax_out + 1) * np.arange(1, lmax_out + 2) CL *= 0.25 * np.arange(lmax_out + 1) * np.arange(1, lmax_out + 2) return GL, CL