def evaluate_subtraction_current(self, current, higher_PS_point=None, momenta_dict=None, reduced_process=None, hel_config=None, **opts): # Just return 0 result = utils.SubtractionCurrentResult() result.add_result(utils.SubtractionCurrentEvaluation.zero(), hel_config=hel_config, squared_orders=tuple( sorted(current.get('squared_orders').items()))) return result
def evaluate_subtraction_current(self, current, higher_PS_point=None, lower_PS_point=None, leg_numbers_map=None, reduced_process=None, hel_config=None, Q=None, **opts): if higher_PS_point is None or lower_PS_point is None: raise CurrentImplementationError( self.name() + " needs the phase-space points before and after mapping.") if leg_numbers_map is None: raise CurrentImplementationError( self.name() + " requires a leg numbers map, i.e. a momentum dictionary.") if reduced_process is None: raise CurrentImplementationError(self.name() + " requires a reduced_process.") if not hel_config is None: raise CurrentImplementationError( self.name() + " does not support helicity assignment.") if Q is None: raise CurrentImplementationError( self.name() + " requires the total mapping momentum Q.") # Retrieve alpha_s and mu_r model_param_dict = self.model.get('parameter_dict') alpha_s = model_param_dict['aS'] mu_r = model_param_dict['MU_R'] # Now find all colored leg numbers in the reduced process all_colored_parton_numbers = [] for leg in reduced_process.get('legs'): if self.model.get_particle(leg.get('id')).get('color') == 1: continue all_colored_parton_numbers.append(leg.get('number')) # Identify the soft leg numbers and momenta soft_leg_number_A = current.get('singular_structure').legs[0].n soft_leg_number_B = current.get('singular_structure').legs[1].n pA = higher_PS_point[soft_leg_number_A] pB = higher_PS_point[soft_leg_number_B] pS = pA + pB # Include the counterterm only in a part of the phase space if self.is_cut(Q=Q, pS=pS): return utils.SubtractionCurrentResult.zero(current=current, hel_config=hel_config) # Now instantiate what the result will be evaluation = utils.SubtractionCurrentEvaluation({ 'spin_correlations': [None], 'color_correlations': [], 'values': {} }) # Normalization factors couplings_factors = 4. * math.pi * alpha_s norm = couplings_factors**2 * self.factor(Q=Q, pS=pS) # Keep track of the color correlators added color_correlators_added = {} color_correlation_max_index = 0 # Now loop over the colored parton numbers to implement the squared double-soft # current flow. Note that significant improvement can be obtained by taking advantage # of the symmetries, as well as writing fully expanded hard-coded expressions with # all dot-products cached. # For efficiency, we choose here to define coefficients of each single product of # correlators. So, typically in the abelian piece, the color correlator reads: # ( '{}' denotes an anti-commutator below and '.' denotes a dot-product ) # { T_i . T_j, T_k . T_l } # And we will register *two* entries: # evaluation['color_correlations'].append( # ( # ( ( (i,-1,i), (k,-2,k) ), ( (j,-1,j), (l,-2,l) ) ), # ) # ) # And: # evaluation['color_correlations'].append( # ( # ( ( (i,-2,i), (k,-1,k) ), ( (j,-2,j), (l,-1,l) ) ), # ) # ) # As opposed to directly defining their sum: # evaluation['color_correlations'].append( # ( # ( ( (i,-1,i), (k,-2,k) ), ( (j,-1,j), (l,-2,l) ) ), # ( ( (i,-2,i), (k,-1,k) ), ( (j,-2,j), (l,-1,l) ) ) # ) # ) for i in all_colored_parton_numbers: for j in all_colored_parton_numbers: # Compute the non-abelian eikonal pi = sum(higher_PS_point[child] for child in leg_numbers_map[i]) pj = sum(higher_PS_point[child] for child in leg_numbers_map[j]) # pi = lower_PS_point[i] # pj = lower_PS_point[j] non_abelian_eikonal = self.non_abelian_eikonal(pi, pj, pA, pB) non_abelian_kernel = -self.CA * norm * non_abelian_eikonal # Implement the non-abelian piece non_abelian_correlator = ((((i, -1, i), ), ((j, -1, j), )), ) if non_abelian_correlator in color_correlators_added: color_correlation_index = color_correlators_added[ non_abelian_correlator] evaluation['values'][(0, color_correlation_index )]['finite'] += non_abelian_kernel else: evaluation['color_correlations'].append( non_abelian_correlator) color_correlation_index = color_correlation_max_index color_correlators_added[ non_abelian_correlator] = color_correlation_max_index color_correlation_max_index += 1 evaluation['values'][(0, color_correlation_index)] = { 'finite': non_abelian_kernel } for k in all_colored_parton_numbers: for l in all_colored_parton_numbers: # Compute the abelian eikonal pk = sum(higher_PS_point[child] for child in leg_numbers_map[k]) pl = sum(higher_PS_point[child] for child in leg_numbers_map[l]) # pk = lower_PS_point[k] # pl = lower_PS_point[l] eik_ij = self.eikonal(pi, pj, pA) eik_kl = self.eikonal(pk, pl, pB) abelian_kernel = 0.5 * norm * eik_ij * eik_kl # Implement the abelian piece abelian_correlator_A = ( self.create_CataniGrazzini_correlator((i, j), (k, l)), ) abelian_correlator_B = ( self.create_CataniGrazzini_correlator((k, l), (i, j)), ) for correlator in [ abelian_correlator_A, abelian_correlator_B ]: if correlator in color_correlators_added: color_correlation_index = color_correlators_added[ correlator] #misc.sprint('Adding %f ((%d,%d,%d)->%f, (%d,%d,%d)->%f) to CC: %d, %s'%\ # (abelian_kernel, # i,j,soft_leg_number_A,self.eikonal(PS_point, i, j, soft_leg_number_A), # k,l,soft_leg_number_B,self.eikonal(PS_point, k, l, soft_leg_number_B), # color_correlation_index, str(correlator) # )) evaluation['values'][( 0, color_correlation_index )]['finite'] += abelian_kernel else: evaluation['color_correlations'].append( correlator) color_correlation_index = color_correlation_max_index color_correlators_added[ correlator] = color_correlation_max_index color_correlation_max_index += 1 evaluation['values'][( 0, color_correlation_index)] = { 'finite': abelian_kernel } #misc.sprint('Adding %f ((%d,%d,%d)->%f, (%d,%d,%d)->%f) to CC: %d, %s'%\ # (abelian_kernel, # i,j,soft_leg_number_A,self.eikonal(PS_point, i, j, soft_leg_number_A), # k,l,soft_leg_number_B,self.eikonal(PS_point, k, l, soft_leg_number_B), # color_correlation_index, str(correlator) # )) result = utils.SubtractionCurrentResult() result.add_result(evaluation, hel_config=hel_config, squared_orders=tuple( sorted(current.get('squared_orders').items()))) #misc.sprint('==BELOW LIST CC==') #for i, cc in enumerate(evaluation['color_correlations']): # misc.sprint('Color correlator: %d : %s = %f'%(i, cc, evaluation['values'][(0,i)]['finite'])) #misc.sprint('==ABOVE LIST CC==') return result
def evaluate_subtraction_current(self, current, higher_PS_point=None, lower_PS_point=None, leg_numbers_map=None, reduced_process=None, hel_config=None, Q=None, **opts): if higher_PS_point is None or lower_PS_point is None: raise CurrentImplementationError( self.name() + " needs the phase-space points before and after mapping.") if leg_numbers_map is None: raise CurrentImplementationError( self.name() + " requires a leg numbers map, i.e. a momentum dictionary.") if not hel_config is None: raise CurrentImplementationError( self.name() + " does not support helicity assignment.") if Q is None: raise CurrentImplementationError( self.name() + " requires the total initial momentum Q.") # Retrieve alpha_s and mu_r model_param_dict = self.model.get('parameter_dict') alpha_s = model_param_dict['aS'] mu_r = model_param_dict['MU_R'] children = self.get_sorted_children(current, self.model) parent = leg_numbers_map.inv[frozenset(children)] pC = sum(higher_PS_point[child] for child in children) qC = lower_PS_point[parent] # Include the counterterm only in a part of the phase space if any(leg.state == leg.INITIAL for leg in current.get('singular_structure').legs): pA = higher_PS_point[children[0]] pR = sum(higher_PS_point[child] for child in children[1:]) # Initial state collinear cut if self.is_cut(Q=Q, pA=pA, pR=pR): return utils.SubtractionCurrentResult.zero( current=current, hel_config=hel_config) else: # Final state collinear cut if self.is_cut(Q=Q, pC=pC): return utils.SubtractionCurrentResult.zero( current=current, hel_config=hel_config) # Evaluate kernel zs, kTs = self.variables(higher_PS_point, qC, children, Q=Q) evaluation = self.evaluate_kernel(zs, kTs, parent) # Add the normalization factors pC2 = pC.square() norm = (8. * math.pi * alpha_s / pC2)**(len(children) - 1) norm *= self.factor(Q=Q, pC=pC, qC=qC) for k in evaluation['values']: evaluation['values'][k]['finite'] *= norm # Construct and return result result = utils.SubtractionCurrentResult() result.add_result(evaluation, hel_config=hel_config, squared_orders=tuple( sorted(current.get('squared_orders').items()))) return result
def evaluate_subtraction_current(self, current, higher_PS_point=None, lower_PS_point=None, reduced_process=None, xi=None, mu_r=None, mu_f=None, Q=None, hel_config=None, allowed_backward_evolved_flavors='ALL', **opts): """ This implementation of the main function call in the base class pre-process the inputs so as to define the variable generically useful for all beam factorization current.""" if not hel_config is None: raise CurrentImplementationError( self.name() + " does not support helicity assignment.") if self.distribution_type != 'endpoint' and xi is None: raise CurrentImplementationError( self.name() + " requires the rescaling variable xi.") if mu_f is None: raise CurrentImplementationError( self.name() + " requires the factorization scale mu_f.") if mu_r is None: raise CurrentImplementationError( self.name() + " requires the factorization scale mu_r.") if lower_PS_point is None: raise CurrentImplementationError( self.name() + " requires a lower PS point to be specified") if reduced_process is None: raise CurrentImplementationError( self.name() + " requires a process instance to be specified") if Q is None: raise CurrentImplementationError( self.name() + " requires the total initial momentum Q.") # Retrieve alpha_s model_param_dict = self.model.get('parameter_dict') alpha_s = model_param_dict['aS'] # Compute the normalization factor normalization = self.SEpsilon * (alpha_s / (2. * math.pi))**(current['n_loops'] + 1) # For beam factorization terms, this function returns an instance of # BeamFactorizationCurrentEvaluation which can specify color-correlations as # well as reduced and resolved flavors. evaluation = self.evaluate_kernel( lower_PS_point, reduced_process, xi, mu_r, mu_f, Q, normalization, allowed_backward_evolved_flavors=allowed_backward_evolved_flavors) # Construct and return result result = utils.SubtractionCurrentResult() result.add_result(evaluation, hel_config=hel_config, squared_orders=tuple( sorted(current.get('squared_orders').items()))) return result
def evaluate_subtraction_current(self, current, higher_PS_point=None, momenta_dict=None, reduced_process=None, hel_config=None, Q=None, **opts): if higher_PS_point is None: raise CurrentImplementationError( self.name() + " needs the phase-space points before mapping.") if momenta_dict is None: raise CurrentImplementationError( self.name() + " requires a momentum routing dictionary.") if not hel_config is None: raise CurrentImplementationError( self.name() + " does not support helicity assignment.") if Q is None: raise CurrentImplementationError( self.name() + " requires the total mapping momentum Q.") # Retrieve alpha_s and mu_r model_param_dict = self.model.get('parameter_dict') alpha_s = model_param_dict['aS'] mu_r = model_param_dict['MU_R'] # Perform mapping this_mapping_singular_structure = self.mapping_singular_structure.get_copy( ) this_mapping_singular_structure.legs = self.get_recoilers( reduced_process) lower_PS_point, mapping_vars = self.mapping.map_to_lower_multiplicity( higher_PS_point, this_mapping_singular_structure, momenta_dict, compute_jacobian=self.divide_by_jacobian) reduced_kinematics = (None, lower_PS_point) # Include the counterterm only in a part of the phase space children = tuple(self.leg_numbers_map[i] for i in sorted(self.leg_numbers_map.keys())) pC_child = higher_PS_point[children[0]] pS = higher_PS_point[children[1]] parent = momenta_dict.inv[frozenset(children)] if self.is_cut(Q=Q, pC=pC_child, pS=pS): return utils.SubtractionCurrentResult.zero( current=current, hel_config=hel_config, reduced_kinematics=('IS_CUT', lower_PS_point)) pC_mother = pC_child - pS pC_tilde = lower_PS_point[parent] # Now instantiate what the result will be evaluation = utils.SubtractionCurrentEvaluation({ 'spin_correlations': [None], 'color_correlations': [None], 'reduced_kinematics': [reduced_kinematics], 'values': { (0, 0, 0): { 'finite': None } } }) # Evaluate kernel xs, kTs = self.variables(higher_PS_point, pC_tilde, children, Q=Q) x = xs[0] # See Eq. (4.17) of NNLO compatible NLO scheme publication arXiv:0903.1218v2 # There is no need for the ratio of color-averaging factor between the real ME # initial state flavor and the one of the reduced Born ME as they are either both # gluons or both quarks evaluation['values'][(0, 0, 0)]['finite'] = self.color_charge * (2. / (1. - x)) # Add the normalization factors # Note: normalising with (pC_tilde+pS).square() will *not* work! norm = 8. * math.pi * alpha_s / (pC_child + pS).square() norm *= self.factor(Q=Q, pC=pC_mother, pS=pS) for k in evaluation['values']: evaluation['values'][k]['finite'] *= norm # Construct and return result result = utils.SubtractionCurrentResult() result.add_result(evaluation, hel_config=hel_config, squared_orders=tuple( sorted(current.get('squared_orders').items()))) return result
def evaluate_subtraction_current(self, current, higher_PS_point=None, momenta_dict=None, reduced_process=None, hel_config=None, **opts): if higher_PS_point is None: raise CurrentImplementationError( self.name() + " needs the higher phase-space point.") if momenta_dict is None: raise CurrentImplementationError(self.name() + " requires a momenta dictionary.") if reduced_process is None: raise CurrentImplementationError(self.name() + " requires a reduced_process.") if not hel_config is None: raise CurrentImplementationError( self.name() + " does not support helicity assignment.") # Retrieve alpha_s and mu_r model_param_dict = self.model.get('parameter_dict') alpha_s = model_param_dict['aS'] mu_r = model_param_dict['MU_R'] # Include the counterterm only in a part of the phase space # Retrieve leg numbers children = tuple(self.leg_numbers_map[i] for i in sorted(self.leg_numbers_map.keys())) parent = momenta_dict.inv[frozenset(children)] # Perform mapping self.mapping_singular_structure.legs = self.get_recoilers( reduced_process, excluded=(parent, )) lower_PS_point, mapping_vars = self.mapping.map_to_lower_multiplicity( higher_PS_point, self.mapping_singular_structure, momenta_dict, compute_jacobian=self.divide_by_jacobian) # Retrieve kinematics Q = mapping_vars['Q'] pC = sum(higher_PS_point[child] for child in children) qC = lower_PS_point[parent] if self.is_cut(Q=Q, pC=pC): return utils.SubtractionCurrentResult.zero(current=current, hel_config=hel_config) reduced_kinematics = (None, lower_PS_point) # Evaluate collinear subtracted kernel zs, kTs = self.variables(higher_PS_point, qC, children, Q=Q) evaluation = self.kernel(zs, kTs, parent, reduced_kinematics) # Start handling the soft counterterms # First check which particles can go soft gluons = [ self.is_gluon(l, self.model) for l in self.structure.get_all_legs() ] # If any can go soft, we need to add eikonal pieces if any(gluons): # Find all colored leg numbers ?except for the parent? in the reduced process all_colored_parton_numbers = [] for leg in reduced_process.get('legs'): if self.model.get_particle(leg.get('id')).get('color') == 1: continue all_colored_parton_numbers.append(leg.get('number')) color_correlation_index = 1 p0 = higher_PS_point[children[0]] p1 = higher_PS_point[children[1]] # Now loop over the colored parton number pairs (parent, j) # and add the corresponding contributions to this current # NB: we are using a (0,1) collinear mapping so in the S(0) limit, parent=p1 # and in the S(1) limit, parent = p0. # As a result, S(0) emitted from the dipole (1,j) has the unresolved color correlation (parent,j) # as well as S(1) emitted from the dipole (0,j). As a result, for each j, we have a single color # correlation for the two eikonal pieces pj.p1/(pj.p0)/(pj.p0+p1.p0) and pj.p0/(pj.p1)/(pj.p1+p0.p1) for j in all_colored_parton_numbers: # Write the eikonal for that pair if j == parent: # j is already the other leg of the dipole, # we skip as we don't handle massive emitters continue pj = higher_PS_point[j] evaluation['color_correlations'].append(((parent, j), )) eiks = 0 if gluons[0]: # Soft 0 emitted from (1,j) with C(0,j) screened eiks -= self.partial_fractionned_eikonal(p1, pj, p0) if gluons[1]: # Soft 1 emitted from (0,j) with C(1,j) screened eiks -= self.partial_fractionned_eikonal(p0, pj, p1) evaluation['values'][(0, color_correlation_index, 0)] = { 'finite': eiks } color_correlation_index += 1 # Add the normalization factors pC2 = pC.square() norm = 8. * math.pi * alpha_s / pC2 norm *= self.factor(Q=Q, pC=pC, qC=qC) for k in evaluation['values']: evaluation['values'][k]['finite'] *= norm # Construct and return result result = utils.SubtractionCurrentResult() result.add_result(evaluation, hel_config=hel_config, squared_orders=tuple( sorted(current.get('squared_orders').items()))) return result
def evaluate_integrated_current(self, current, PS_point, reduced_process=None, leg_numbers_map=None, hel_config=None, compute_poles=False, **opts): """ Now evalaute the current and return the corresponding instance of SubtractionCurrentResult. See documentation of the mother function for more details.""" if not hel_config is None: raise CurrentImplementationError( "Subtraction current implementation " + "%s does not support helicity assignment." % self.__class__.__name__) if leg_numbers_map is None: raise CurrentImplementationError( "Subtraction current implementation " + "%s requires the leg_number_map." % self.__class__.__name__) if reduced_process is None: raise CurrentImplementationError( "Subtraction current implementation " + "%s requires the reduced_process." % self.__class__.__name__) result = utils.SubtractionCurrentResult() ss = current.get('singular_structure').substructures[0] # Retrieve alpha_s and mu_r model_param_dict = self.model.get('parameter_dict') alpha_s = model_param_dict['aS'] mu_r = model_param_dict['MU_R'] # Retrieve kinematic variables from the specified PS point children_numbers = tuple(leg.n for leg in ss.legs) parent_number = leg_numbers_map.inv[frozenset(children_numbers)] p12 = PS_point[parent_number] Q = sum([ PS_point[l.get('number')] for l in reduced_process.get_initial_legs() ]) Q_square = Q.square() y12 = 2. * Q.dot(p12) / Q_square # Now instantiate what the result will be evaluation = utils.SubtractionCurrentEvaluation({ 'spin_correlations': [None], 'color_correlations': [None], 'values': { (0, 0): {} } }) #Virtuality cut in the integration alpha_0 = currents.SomogyiChoices.alpha_0 finite_part = HE.CggFF_Finite_Gabor_DIVJAC_NOD0(alpha_0, y12) value = EpsilonExpansion({ 0: finite_part, -1: (11. / 3. - 4. * math.log(y12)), -2: 2. }) logMuQ = math.log(mu_r**2 / Q_square) prefactor = EpsilonExpansion({0: 1., 1: logMuQ, 2: 0.5 * logMuQ**2}) prefactor *= self.SEpsilon # Now add the normalization factors value *= prefactor * (alpha_s / (2. * math.pi)) * self.CA # Truncate expansion so as to keep only relevant terms value.truncate(min_power=-2, max_power=0) # Now register the value in the evaluation evaluation['values'][(0, 0)] = value.to_human_readable_dict() # And add it to the results result.add_result(evaluation, hel_config=hel_config, squared_orders=tuple( sorted(current.get('squared_orders').items()))) return result
def evaluate_subtraction_current( self, current, higher_PS_point=None, momenta_dict=None, reduced_process=None, hel_config=None, Q=None, **opts): if higher_PS_point is None: raise CurrentImplementationError( self.name() + " needs the phase-space points before and after mapping.") if momenta_dict is None: raise CurrentImplementationError( self.name() + " requires a momentum routing dictionary.") if reduced_process is None: raise CurrentImplementationError( self.name() + " requires a reduced_process.") if not hel_config is None: raise CurrentImplementationError( self.name() + " does not support helicity assignment.") if Q is None: raise CurrentImplementationError( self.name() + " requires the total mapping momentum Q.") # Retrieve alpha_s and mu_r model_param_dict = self.model.get('parameter_dict') alpha_s = model_param_dict['aS'] mu_r = model_param_dict['MU_R'] # Now find all colored leg numbers in the reduced process all_colored_parton_numbers = [] for leg in reduced_process.get('legs'): if self.model.get_particle(leg.get('id')).get('color') == 1: continue all_colored_parton_numbers.append(leg.get('number')) soft_momenta = [ higher_PS_point[self.leg_numbers_map[soft_leg_number]] for soft_leg_number in self.leg_numbers_map if soft_leg_number>9 ] pS = sum(soft_momenta) # Perform mapping this_mapping_singular_structure = self.mapping_singular_structure.get_copy() this_mapping_singular_structure.legs = self.get_recoilers(reduced_process) lower_PS_point, mapping_vars = self.mapping.map_to_lower_multiplicity( higher_PS_point, this_mapping_singular_structure, momenta_dict, compute_jacobian=self.divide_by_jacobian) reduced_kinematics = (None, lower_PS_point) jacobian = mapping_vars.get('jacobian', 1.) # Include the counterterm only in a part of the phase space if self.is_cut(Q=Q, pS=pS): return utils.SubtractionCurrentResult.zero( current=current, hel_config=hel_config, reduced_kinematics=('IS_CUT', lower_PS_point)) # Now instantiate what the result will be evaluation = utils.SubtractionCurrentEvaluation({ 'spin_correlations': [None], 'color_correlations': [], 'reduced_kinematics': [reduced_kinematics, ], 'values': {} }) # Normalization factors norm = (8. * math.pi * alpha_s)**(len(soft_momenta))*(1./pS.square()**2) norm *= self.factor(Q=Q, pS=pS) if self.divide_by_jacobian: norm /= jacobian colored_partons_momenta = vectors.LorentzVectorDict() for colored_parton_number in all_colored_parton_numbers: # We want to used the reduced kinematics for our soft current colored_partons_momenta[colored_parton_number] = lower_PS_point[colored_parton_number] # Alternatively, the expression below would have given us the resolved one #colored_partons_momenta[colored_parton_number] = sum(higher_PS_point[child] for child in momenta_dict[colored_parton_number]) color_correlation_index = 0 for color_correlator, weight in self.soft_kernel( self, colored_partons_momenta, soft_momenta, all_colored_parton_numbers): evaluation['color_correlations'].append(color_correlator) complete_weight = weight*norm evaluation['values'][(0, color_correlation_index, 0)] = {'finite': complete_weight[0]} color_correlation_index += 1 result = utils.SubtractionCurrentResult() result.add_result( evaluation, hel_config=hel_config, squared_orders=tuple(sorted(current.get('squared_orders').items()))) return result
def evaluate_subtraction_current(self, current, higher_PS_point=None, momenta_dict=None, reduced_process=None, hel_config=None, Q=None, **opts): if higher_PS_point is None: raise CurrentImplementationError( self.name() + " needs the higher phase-space point.") if momenta_dict is None: raise CurrentImplementationError(self.name() + " requires a momenta dictionary.") if reduced_process is None: raise CurrentImplementationError(self.name() + " requires a reduced_process.") if not hel_config is None: raise CurrentImplementationError( self.name() + " does not support helicity assignment.") if Q is None: raise CurrentImplementationError( self.name() + " requires specification of the total incoming momentum Q.") # Retrieve alpha_s and mu_r model_param_dict = self.model.get('parameter_dict') alpha_s = model_param_dict['aS'] mu_r = model_param_dict['MU_R'] # Retrieve leg numbers children = tuple(self.leg_numbers_map[i] for i in sorted(self.leg_numbers_map.keys())) parent = momenta_dict.inv[frozenset(children)] # Perform mapping self.mapping_singular_structure.legs = self.get_recoilers( reduced_process, excluded=(parent, )) lower_PS_point, mapping_vars = self.mapping.map_to_lower_multiplicity( higher_PS_point, self.mapping_singular_structure, momenta_dict, compute_jacobian=self.divide_by_jacobian) # Retrieve kinematics # The Q variable of the mapping cannot be relied upon #Q = mapping_vars['Q'] if self.has_initial_state: pC = higher_PS_point[children[0]] - sum(higher_PS_point[child] for child in children[1:]) else: pC = sum(higher_PS_point[child] for child in children) qC = lower_PS_point[parent] jacobian = mapping_vars.get('jacobian', 1) reduced_kinematics = (None, lower_PS_point) # Include the counterterm only in a part of the phase space if self.has_initial_state: pA = higher_PS_point[children[0]] pR = sum(higher_PS_point[child] for child in children[1:]) # Initial state collinear cut if self.is_cut(Q=Q, pA=pA, pR=pR): return utils.SubtractionCurrentResult.zero( current=current, hel_config=hel_config, reduced_kinematics=('IS_CUT', lower_PS_point)) else: # Final state collinear cut if self.is_cut(Q=Q, pC=pC): return utils.SubtractionCurrentResult.zero( current=current, hel_config=hel_config, reduced_kinematics=('IS_CUT', lower_PS_point)) # Evaluate kernel # First construct variables necessary for its evaluation # pass the mapping variables to the variables function, except for Q which is provided externally mapping_vars.pop('Q', None) kernel_arguments = self.variables(higher_PS_point, qC, children, Q=Q, **mapping_vars) evaluation = utils.SubtractionCurrentEvaluation({ 'spin_correlations': [ None, ], 'color_correlations': [ None, ], 'reduced_kinematics': [reduced_kinematics], 'values': {} }) evaluation = self.kernel(evaluation, parent, *kernel_arguments) # Add the normalization factors pC2 = pC.square() norm = (8. * math.pi * alpha_s / pC2)**(len(children) - 1) norm *= self.factor(Q=Q, pC=pC, qC=qC) norm /= jacobian for k in evaluation['values']: evaluation['values'][k]['finite'] *= norm # Construct and return result result = utils.SubtractionCurrentResult() result.add_result(evaluation, hel_config=hel_config, squared_orders=tuple( sorted(current.get('squared_orders').items()))) return result
def evaluate_subtraction_current( self, current, higher_PS_point=None, lower_PS_point=None, leg_numbers_map=None, reduced_process=None, hel_config=None, Q=None, **opts ): if higher_PS_point is None or lower_PS_point is None: raise CurrentImplementationError( self.name() + " needs the phase-space points before and after mapping." ) if leg_numbers_map is None: raise CurrentImplementationError( self.name() + " requires a leg numbers map, i.e. a momentum dictionary." ) if not hel_config is None: raise CurrentImplementationError( self.name() + " does not support helicity assignment." ) if Q is None: raise CurrentImplementationError( self.name() + " requires the total mapping momentum Q." ) # Retrieve alpha_s and mu_r model_param_dict = self.model.get('parameter_dict') alpha_s = model_param_dict['aS'] mu_r = model_param_dict['MU_R'] # Include the counterterm only in a part of the phase space children = self.get_sorted_children(current, self.model) pC = higher_PS_point[children[0]] pS = higher_PS_point[children[1]] pC = pC + pS parent = leg_numbers_map.inv[frozenset(children)] if self.is_cut(Q=Q, pC=pC, pS=pS): return utils.SubtractionCurrentResult.zero( current=current, hel_config=hel_config) # Now instantiate what the result will be evaluation = utils.SubtractionCurrentEvaluation({ 'spin_correlations': [None], 'color_correlations': [None], 'values': {(0, 0): {'finite': None}} }) # Evaluate kernel xs, kTs = self.variables(higher_PS_point, lower_PS_point[parent], children, Q=Q) x = xs[0] # See Eq. (4.17) of NNLO compatible NLO scheme publication arXiv:0903.1218v2 # There is no need for the ratio of color-averaging factor between the real ME # initial state flavor and the one of the reduced Born ME as they are either both # gluons or both quarks evaluation['values'][(0, 0)]['finite'] = self.color_charge * ( 2. / (1. - x) ) # Add the normalization factors s12 = pC.square() norm = 8. * math.pi * alpha_s / s12 norm *= self.factor(Q=Q, pC=pC, pS=pS) for k in evaluation['values']: evaluation['values'][k]['finite'] *= norm # Construct and return result result = utils.SubtractionCurrentResult() result.add_result( evaluation, hel_config=hel_config, squared_orders=tuple(sorted(current.get('squared_orders').items()))) return result
def evaluate_subtraction_current( self, current, higher_PS_point=None, lower_PS_point=None, leg_numbers_map=None, reduced_process=None, hel_config=None, Q=None, **opts ): if higher_PS_point is None or lower_PS_point is None: raise CurrentImplementationError( self.name() + " needs the phase-space points before and after mapping." ) if leg_numbers_map is None: raise CurrentImplementationError( self.name() + " requires a leg numbers map, i.e. a momentum dictionary." ) if not hel_config is None: raise CurrentImplementationError( self.name() + " does not support helicity assignment." ) if Q is None: raise CurrentImplementationError( self.name() + " requires the total mapping momentum Q." ) # Retrieve alpha_s and mu_r model_param_dict = self.model.get('parameter_dict') alpha_s = model_param_dict['aS'] mu_r = model_param_dict['MU_R'] # Include the counterterm only in a part of the phase space children = self.get_sorted_children(current, self.model) pC = sum(higher_PS_point[child] for child in children) soft_children = [] for substructure in current.get('singular_structure').substructures: soft_children += [leg.n for leg in substructure.get_all_legs()] pS = sum(higher_PS_point[child] for child in soft_children) parent = leg_numbers_map.inv[frozenset(children)] if self.is_cut(Q=Q, pC=pC, pS=pS): return utils.SubtractionCurrentResult.zero( current=current, hel_config=hel_config) # Now instantiate what the result will be evaluation = utils.SubtractionCurrentEvaluation({ 'spin_correlations': [None], 'color_correlations': [None], 'values': {(0, 0): {'finite': None}} }) # Evaluate kernel zs, kTs = self.variables(higher_PS_point, lower_PS_point[parent], children, Q=Q) z = zs[0] evaluation['values'][(0, 0)]['finite'] = self.color_charge * 2.*(1.-z) / z # Add the normalization factors s12 = pC.square() norm = 8. * math.pi * alpha_s / s12 norm *= self.factor(Q=Q, pC=pC, pS=pS) for k in evaluation['values']: evaluation['values'][k]['finite'] *= norm # Construct and return result result = utils.SubtractionCurrentResult() result.add_result( evaluation, hel_config=hel_config, squared_orders=tuple(sorted(current.get('squared_orders').items()))) return result
def evaluate_subtraction_current( self, current, higher_PS_point=None, lower_PS_point=None, leg_numbers_map=None, reduced_process=None, hel_config=None, Q=None, **opts ): if higher_PS_point is None or lower_PS_point is None: raise CurrentImplementationError( self.name() + " needs the phase-space points before and after mapping." ) if leg_numbers_map is None: raise CurrentImplementationError( self.name() + " requires a leg numbers map, i.e. a momentum dictionary." ) if reduced_process is None: raise CurrentImplementationError( self.name() + " requires a reduced_process.") if not hel_config is None: raise CurrentImplementationError( self.name() + " does not support helicity assignment." ) if Q is None: raise CurrentImplementationError( self.name() + " requires the total mapping momentum Q." ) # Retrieve alpha_s and mu_r model_param_dict = self.model.get('parameter_dict') alpha_s = model_param_dict['aS'] mu_r = model_param_dict['MU_R'] # Now find all colored leg numbers in the reduced process all_colored_parton_numbers = [] for leg in reduced_process.get('legs'): if self.model.get_particle(leg.get('id')).get('color')==1: continue all_colored_parton_numbers.append(leg.get('number')) soft_leg_number = current.get('singular_structure').legs[0].n pS = higher_PS_point[soft_leg_number] # Include the counterterm only in a part of the phase space if self.is_cut(Q=Q, pS=pS): return utils.SubtractionCurrentResult.zero( current=current, hel_config=hel_config) # Now instantiate what the result will be evaluation = utils.SubtractionCurrentEvaluation({ 'spin_correlations' : [ None ], 'color_correlations' : [], 'values' : {} }) # Normalization factors norm = -4. * math.pi * alpha_s norm *= self.factor(Q=Q, pS=pS) color_correlation_index = 0 # Now loop over the colored parton number pairs (a,b) # and add the corresponding contributions to this current for i, a in enumerate(all_colored_parton_numbers): # Use the symmetry of the color correlation and soft current (a,b) <-> (b,a) for b in all_colored_parton_numbers[i:]: # Write the eikonal for that pair if a!=b: mult_factor = 2. else: mult_factor = 1. pa = sum(higher_PS_point[child] for child in leg_numbers_map[a]) pb = sum(higher_PS_point[child] for child in leg_numbers_map[b]) # pa = lower_PS_point[a] # pb = lower_PS_point[b] eikonal = self.eikonal(pa, pb, pS) evaluation['color_correlations'].append( ((a, b), ) ) evaluation['values'][(0, color_correlation_index)] = { 'finite': norm * mult_factor * eikonal } color_correlation_index += 1 result = utils.SubtractionCurrentResult() result.add_result( evaluation, hel_config=hel_config, squared_orders=tuple(sorted(current.get('squared_orders').items())) ) return result
def evaluate_subtraction_current( self, current, higher_PS_point=None, lower_PS_point=None, leg_numbers_map=None, reduced_process=None, hel_config=None, Q=None, **opts ): """Add the distributed partial fractioned soft eikonal approximation to this hard collinear current """ if higher_PS_point is None or lower_PS_point is None: raise CurrentImplementationError( self.name() + " needs the phase-space points before and after mapping." ) if leg_numbers_map is None: raise CurrentImplementationError( self.name() + " requires a leg numbers map, i.e. a momentum dictionary." ) if reduced_process is None: raise CurrentImplementationError( self.name() + " requires a reduced_process.") if not hel_config is None: raise CurrentImplementationError( self.name() + " does not support helicity assignment." ) if Q is None: raise CurrentImplementationError( self.name() + " requires the total mapping momentum Q." ) # Retrieve alpha_s and mu_r model_param_dict = self.model.get('parameter_dict') alpha_s = model_param_dict['aS'] mu_r = model_param_dict['MU_R'] # Include the counterterm only in a part of the phase space children = self.get_sorted_children(current, self.model) parent = leg_numbers_map.inv[frozenset(children)] pC = higher_PS_point[children[0]] pC -= sum(higher_PS_point[child] for child in children[1:]) if self.is_cut(Q=Q, pC=pC): return utils.SubtractionCurrentResult.zero( current=current, hel_config=hel_config) # Evaluate collinear subtracted kernel zs, kTs = self.variables(higher_PS_point, lower_PS_point[parent], children, Q=Q) evaluation = self.evaluate_kernel(zs, kTs, parent) # Find all colored leg numbers except for the parent in the reduced process all_colored_parton_numbers = [] for leg in reduced_process.get('legs'): if self.model.get_particle(leg.get('id')).get('color') == 1: continue all_colored_parton_numbers.append(leg.get('number')) color_correlation_index = 1 ps = higher_PS_point[children[1]] pi = higher_PS_point[children[0]] # pi = lower_PS_point[parent] # Loop over the colored parton number pairs (parent, j) # and add the corresponding contributions to this current for j in all_colored_parton_numbers: # Write the eikonal for that pair # (positive here since the dipole end 'children[0]' is in the initial state) if j == parent: continue pj = higher_PS_point[j] # pj = sum(higher_PS_point[child] for child in leg_numbers_map[j]) # pj = lower_PS_point[j] eik1 = mod_eikonal(pi, pj, ps) evaluation['color_correlations'].append(((parent, j),)) evaluation['values'][(0, color_correlation_index)] = {'finite': eik1} color_correlation_index += 1 # Add the normalization factors pC2 = pC.square() norm = 8. * math.pi * alpha_s / pC2 norm *= self.factor(Q=Q, pC=pC) for k in evaluation['values']: evaluation['values'][k]['finite'] *= norm # Construct and return result result = utils.SubtractionCurrentResult() result.add_result( evaluation, hel_config=hel_config, squared_orders=tuple(sorted(current.get('squared_orders').items()))) return result
def evaluate_subtraction_current( self, current, higher_PS_point=None, momenta_dict=None, reduced_process=None, hel_config=None, **opts ): if higher_PS_point is None: raise CurrentImplementationError( self.name() + " needs the higher phase-space point." ) if momenta_dict is None: raise CurrentImplementationError( self.name() + " requires a momenta dictionary." ) if reduced_process is None: raise CurrentImplementationError( self.name() + " requires a reduced_process.") if not hel_config is None: raise CurrentImplementationError( self.name() + " does not support helicity assignment." ) # Retrieve alpha_s and mu_r model_param_dict = self.model.get('parameter_dict') alpha_s = model_param_dict['aS'] mu_r = model_param_dict['MU_R'] # Retrieve leg numbers soft_leg_number = self.leg_numbers_map[0] # Perform mapping self.mapping_singular_structure.legs = self.get_recoilers(reduced_process) lower_PS_point, mapping_vars = soft_mapping.map_to_lower_multiplicity( higher_PS_point, self.mapping_singular_structure, momenta_dict, compute_jacobian=self.divide_by_jacobian ) # Retrieve kinematics Q = mapping_vars['Q'] pS = higher_PS_point[soft_leg_number] jacobian = mapping_vars.get('jacobian', 1) # Include the counterterm only in a part of the phase space if self.is_cut(Q=Q, pS=pS): return utils.SubtractionCurrentResult.zero( current=current, hel_config=hel_config, reduced_kinematics=(None, lower_PS_point)) # Normalization factors norm = -4 * math.pi * alpha_s norm *= self.factor(Q=Q, pS=pS) norm /= jacobian # Find all colored leg numbers in the reduced process all_colored_parton_numbers = [] for leg in reduced_process.get('legs'): if self.model.get_particle(leg.get('id')).get('color') == 1: continue all_colored_parton_numbers.append(leg.get('number')) # Initialize the result evaluation = utils.SubtractionCurrentEvaluation({ 'spin_correlations': [None], 'color_correlations': [], 'reduced_kinematics': [(None, lower_PS_point)], 'values': {} }) # Loop over colored parton number pairs (a, b) # and add the corresponding contributions to this current color_correlation_index = 0 for i, a in enumerate(all_colored_parton_numbers): # Use the symmetry of the color correlation and soft current (a,b) <-> (b,a) for b in all_colored_parton_numbers[i:]: # Write the eikonal for that pair if a != b: mult_factor = 2. else: mult_factor = 1. pa = higher_PS_point[a] pb = higher_PS_point[b] eikonal = self.eikonal(pa, pb, pS) evaluation['color_correlations'].append( ((a, b), ) ) evaluation['values'][(0, color_correlation_index, 0)] = { 'finite': norm * mult_factor * eikonal } color_correlation_index += 1 result = utils.SubtractionCurrentResult() result.add_result( evaluation, hel_config=hel_config, squared_orders=tuple(sorted(current.get('squared_orders').items())) ) return result
def evaluate_subtraction_current(self, current, higher_PS_point=None, momenta_dict=None, reduced_process=None, hel_config=None, Q=None, **opts): if higher_PS_point is None: raise CurrentImplementationError( self.name() + " needs the higher phase-space point.") if momenta_dict is None: raise CurrentImplementationError(self.name() + " requires a momenta dictionary.") if reduced_process is None: raise CurrentImplementationError(self.name() + " requires a reduced_process.") if not hel_config is None: raise CurrentImplementationError( self.name() + " does not support helicity assignment.") if Q is None: raise CurrentImplementationError( self.name() + " requires specification of the total incoming momentum Q.") # Retrieve alpha_s and mu_r model_param_dict = self.model.get('parameter_dict') alpha_s = model_param_dict['aS'] mu_r = model_param_dict['MU_R'] # Retrieve leg numbers overall_children = [ ] # the legs becoming unresolved in the resolved process (momenta in the real-emission ME) overall_parents = [ ] # the parent legs in the top-level reduced process (momenta in the mapped ME of this CT) # We take one defining structure (self.structure[0]). Its top-level substructures are the independent bundles # eg (C(1,2),C(4,5),S(6)). # Using structure[0] as the defining structure is fine for the purpose below since they should # all use the same leg numbers for bundle in self.structure[0].substructures: overall_children.append( tuple(self.leg_numbers_map[l.n] for l in bundle.get_all_legs())) if self.has_parent(bundle, len(overall_children[-1])): overall_parents.append( self.get_parent(frozenset(overall_children[-1]), momenta_dict)) else: overall_parents.append(None) all_steps = [ { 'higher_PS_point': higher_PS_point }, ] overall_jacobian = 1. for i_step, mapping_information in enumerate(self.mapping_rules): # Now obtain recoilers reduced_recoilers = mapping_information['reduced_recoilers']( reduced_process, excluded=tuple(overall_parents)) additional_recoilers = sub.SubtractionLegSet( SubtractionLeg(self.map_leg_number(l.n, overall_parents), l.pdg, l.state) for l in mapping_information['additional_recoilers']) all_recoilers = sub.SubtractionLegSet( list(reduced_recoilers) + list(additional_recoilers)) # Now recursively apply leg numbers mappings mapping_singular_structure = mapping_information[ 'singular_structure'].get_copy() self.map_leg_numbers_in_singular_structure( mapping_singular_structure, overall_parents) # Now assign the recoilers (whose leg numbers have already been mapped) mapping_singular_structure.legs = all_recoilers # Build the momenta_dict by also substituting leg numbers this_momenta_dict = bidict({ self.map_leg_number(k, overall_parents): frozenset([self.map_leg_number(n, overall_parents) for n in v]) for k, v in mapping_information['momenta_dict'].items() }) lower_PS_point, mapping_vars = mapping_information[ 'mapping'].map_to_lower_multiplicity( all_steps[-1]['higher_PS_point'], mapping_singular_structure, this_momenta_dict, compute_jacobian=self.divide_by_jacobian) if mappings.RelabellingMapping.needs_relabelling( this_momenta_dict): lower_PS_point = mappings.RelabellingMapping.map_to_lower_multiplicity( lower_PS_point, None, this_momenta_dict) all_steps[-1]['lower_PS_point'] = lower_PS_point # Q is provided externally mapping_vars.pop('Q', None) all_steps[-1]['mapping_vars'] = mapping_vars overall_jacobian *= mapping_vars.get('jacobian', 1.) bundles_info = [] for bundle in mapping_singular_structure.substructures: bundles_info.append({}) all_legs = bundle.get_all_legs() # This sorting is important so that the variables generated can be related to the legs specified # in the mapping singular structures of the mapping rules all_initial_legs = sorted( [l for l in all_legs if l.state == l.INITIAL], key=lambda l: l.n) all_final_legs = sorted( [l for l in all_legs if l.state == l.FINAL], key=lambda l: l.n) bundles_info[-1]['initial_state_children'] = tuple( l.n for l in all_initial_legs) bundles_info[-1]['final_state_children'] = tuple( l.n for l in all_final_legs) if self.has_parent(bundle, len(all_legs)): bundles_info[-1]['parent'] = self.get_parent( frozenset(l.n for l in all_legs), this_momenta_dict) else: bundles_info[-1]['parent'] = None # Retrieve kinematics bundles_info[-1]['cut_inputs'] = {} if bundle.name() == 'C': if len(all_initial_legs) > 0: bundles_info[-1]['cut_inputs']['pA'] = -sum( all_steps[-1]['higher_PS_point'][l.n] for l in all_initial_legs) bundles_info[-1]['cut_inputs']['pC'] = sum( all_steps[-1]['higher_PS_point'][l.n] for l in all_final_legs) elif bundle.name() == 'S': bundles_info[-1]['cut_inputs']['pS'] = sum( all_steps[-1]['higher_PS_point'][l.n] for l in all_final_legs) all_steps[-1]['bundles_info'] = bundles_info # Get all variables for this level if mapping_information['variables'] is not None: all_steps[-1]['variables'] = mapping_information['variables']( all_steps[-1]['higher_PS_point'], all_steps[-1]['lower_PS_point'], bundles_info, Q=Q, **mapping_vars) else: all_steps[-1]['variables'] = {} # Add the next higher PS point for the next level if necessary if i_step < (len(self.mapping_rules) - 1): all_steps.append({'higher_PS_point': lower_PS_point}) overall_lower_PS_point = all_steps[-1]['lower_PS_point'] reduced_kinematics = (None, overall_lower_PS_point) global_variables = { 'overall_children': overall_children, 'overall_parents': overall_parents, 'leg_numbers_map': self.leg_numbers_map, 'Q': Q, } # Build global variables if necessary if self.variables is not None: global_variables.update(self.variables(all_steps, global_variables)) # Apply cuts: include the counterterm only in a part of the phase-space for i_step, step_info in enumerate(all_steps): cut_inputs = dict(step_info) if self.mapping_rules[i_step]['is_cut'](cut_inputs, global_variables): return utils.SubtractionCurrentResult.zero( current=current, hel_config=hel_config, reduced_kinematics=('IS_CUT', overall_lower_PS_point)) # for i_step, step_info in enumerate(all_steps): # misc.sprint("Higher PS point at step #%d: %s"%(i_step, str(step_info['higher_PS_point']))) # misc.sprint("Lower PS point at step #%d: %s"%(i_step, str(step_info['lower_PS_point']))) # Evaluate kernel evaluation = utils.SubtractionCurrentEvaluation({ 'spin_correlations': [ None, ], 'color_correlations': [ None, ], 'reduced_kinematics': [ reduced_kinematics, ], 'values': {} }) # Apply collinear kernel (can be dummy) evaluation = self.kernel(evaluation, all_steps, global_variables) # Apply soft kernel (can be dummy), which also knows about the reduced process evaluation = self.call_soft_kernel(evaluation, reduced_process, all_steps, global_variables) # Add the normalization factors # WARNING! In this implementation the propagator denominators must be included in the kernel evaluation. norm = (8. * math.pi * alpha_s)**(self.squared_orders['QCD'] / 2) norm /= overall_jacobian for k in evaluation['values']: for term in evaluation['values'][k]: evaluation['values'][k][term] *= norm # Construct and return result result = utils.SubtractionCurrentResult() result.add_result(evaluation, hel_config=hel_config, squared_orders=tuple( sorted(current.get('squared_orders').items()))) return result
def evaluate_subtraction_current( self, current, higher_PS_point=None, momenta_dict=None, reduced_process=None, hel_config=None, **opts ): if higher_PS_point is None: raise CurrentImplementationError( self.name() + " needs the higher phase-space point." ) if momenta_dict is None: raise CurrentImplementationError( self.name() + " requires a momenta dictionary." ) if reduced_process is None: raise CurrentImplementationError( self.name() + " requires a reduced_process.") if not hel_config is None: raise CurrentImplementationError( self.name() + " does not support helicity assignment." ) # Retrieve alpha_s and mu_r model_param_dict = self.model.get('parameter_dict') alpha_s = model_param_dict['aS'] mu_r = model_param_dict['MU_R'] # Retrieve leg numbers soft_leg_number = self.leg_numbers_map[0] coll_leg_number = self.leg_numbers_map[1] children = (soft_leg_number, coll_leg_number, ) parent = momenta_dict.inv[frozenset(children)] # Perform mapping self.mapping_singular_structure.legs = self.get_recoilers( reduced_process, excluded=(parent, )) lower_PS_point, mapping_vars = self.mapping.map_to_lower_multiplicity( higher_PS_point, self.mapping_singular_structure, momenta_dict, compute_jacobian=self.divide_by_jacobian ) # Retrieve kinematics Q = mapping_vars['Q'] pS = higher_PS_point[soft_leg_number] pC = pS + higher_PS_point[coll_leg_number] jacobian = mapping_vars.get('jacobian', 1) # Include the counterterm only in a part of the phase space if self.is_cut(Q=Q, pS=pS): return utils.SubtractionCurrentResult.zero( current=current, hel_config=hel_config, reduced_kinematics=(None, lower_PS_point)) # Evaluate kernel zs, kTs = self.variables(higher_PS_point, lower_PS_point[parent], children, Q=Q) z = zs[0] evaluation = utils.SubtractionCurrentEvaluation.zero( reduced_kinematics=(None, lower_PS_point)) evaluation['values'][(0, 0, 0)]['finite'] = self.color_charge * 2 * (1-z) / z # Add the normalization factors s12 = pC.square() norm = 8 * math.pi * alpha_s / s12 norm *= self.factor(Q=Q, pC=pC, pS=pS) norm /= jacobian for k in evaluation['values']: evaluation['values'][k]['finite'] *= norm # Construct and return result result = utils.SubtractionCurrentResult() result.add_result( evaluation, hel_config=hel_config, squared_orders=tuple(sorted(current.get('squared_orders').items()))) return result
def evaluate_subtraction_current(self, current, higher_PS_point=None, momenta_dict=None, reduced_process=None, hel_config=None, Q=None, **opts): if higher_PS_point is None: raise CurrentImplementationError( self.name() + " needs the phase-space points before and after mapping.") if momenta_dict is None: raise CurrentImplementationError( self.name() + " requires a momentum routing dictionary.") if reduced_process is None: raise CurrentImplementationError(self.name() + " requires a reduced_process.") if not hel_config is None: raise CurrentImplementationError( self.name() + " does not support helicity assignment.") if Q is None: raise CurrentImplementationError( self.name() + " requires the total mapping momentum Q.") """Important note about the IF CS: - in this scheme we want to use "tilded" momenta for the dipole legs in eikonals. This is explicitly implemented in the soft local current - this implies that the correct form for the local C(ir)S(r) taken as the collinear limit of the eikonals is 1/ (p_r + p_i_tilde)^2 (1-z_r)/z_r where z_r = p_r.Q/(p_r+p_i_tilde).Q - Specializing to the case where the collinear partner of the soft particle is an initial state particle (i = a ), we have p_a_tilde = xi p_a and 2p_a.Q = Q^2 so that the soft-collinear takes the form 1/(p_r+xi p_a)^2 * xi/y_rQ where y_rQ is the usual Hungarian variable this simplifies to 1/(p_r+p_a)^2 * 1/y_rQ which is exactly the soft collinear as computed *without* tilded variables (i.e. exactly eq.5.29 of 0903.1218) As a result we use exactly the same way of evaluating the counterterms as in honest-to-god colorful. """ # Retrieve alpha_s and mu_r model_param_dict = self.model.get('parameter_dict') alpha_s = model_param_dict['aS'] mu_r = model_param_dict['MU_R'] # Now find all colored leg numbers in the reduced process all_colored_parton_numbers = [] for leg in reduced_process.get('legs'): if self.model.get_particle(leg.get('id')).get('color') == 1: continue all_colored_parton_numbers.append(leg.get('number')) soft_leg_number = self.leg_numbers_map[0] pS = higher_PS_point[soft_leg_number] # Perform mapping this_mapping_singular_structure = self.mapping_singular_structure.get_copy( ) this_mapping_singular_structure.legs = self.get_recoilers( reduced_process) lower_PS_point, mapping_vars = self.mapping.map_to_lower_multiplicity( higher_PS_point, this_mapping_singular_structure, momenta_dict, compute_jacobian=self.divide_by_jacobian) reduced_kinematics = (None, lower_PS_point) # Include the counterterm only in a part of the phase space if self.is_cut(Q=Q, pS=pS): return utils.SubtractionCurrentResult.zero( current=current, hel_config=hel_config, reduced_kinematics=('IS_CUT', lower_PS_point)) # Retrieve kinematics pS = higher_PS_point[soft_leg_number] jacobian = mapping_vars.get('jacobian', 1.) # Now instantiate what the result will be evaluation = utils.SubtractionCurrentEvaluation({ 'spin_correlations': [None], 'color_correlations': [], 'reduced_kinematics': [ reduced_kinematics, ], 'values': {} }) # Normalization factors norm = -4. * math.pi * alpha_s norm *= self.factor(Q=Q, pS=pS) if self.divide_by_jacobian: norm /= jacobian color_correlation_index = 0 # Now loop over the colored parton number pairs (a,b) # and add the corresponding contributions to this current for i, a in enumerate(all_colored_parton_numbers): # Use the symmetry of the color correlation and soft current (a,b) <-> (b,a) for b in all_colored_parton_numbers[i:]: # Write the eikonal for that pair if a != b: mult_factor = 2. else: mult_factor = 1. #pa = sum(higher_PS_point[child] for child in momenta_dict[a]) #pb = sum(higher_PS_point[child] for child in momenta_dict[b]) pa = lower_PS_point[a] pb = lower_PS_point[b] eikonal = self.eikonal(pa, pb, pS) evaluation['color_correlations'].append(((a, b), )) evaluation['values'][(0, color_correlation_index, 0)] = { 'finite': norm * mult_factor * eikonal } color_correlation_index += 1 result = utils.SubtractionCurrentResult() result.add_result(evaluation, hel_config=hel_config, squared_orders=tuple( sorted(current.get('squared_orders').items()))) return result
def evaluate_subtraction_current( self, current, higher_PS_point=None, momenta_dict=None, reduced_process=None, hel_config=None, Q=None, **opts ): if higher_PS_point is None: raise CurrentImplementationError( self.name() + " needs the phase-space points before mapping." ) if momenta_dict is None: raise CurrentImplementationError( self.name() + " requires a momentum routing dictionary." ) if not hel_config is None: raise CurrentImplementationError( self.name() + " does not support helicity assignment." ) if Q is None: raise CurrentImplementationError( self.name() + " requires the total mapping momentum Q." ) """Important note about the IF CS: - in this scheme we want to use "tilded" momenta for the dipole legs in eikonals. This is explicitly implemented in the soft local current - this implies that the correct form for the local C(ir)S(r) taken as the collinear limit of the eikonals is 1/ (p_r + p_i_tilde)^2 (1-z_r)/z_r where z_r = p_r.Q/(p_r+p_i_tilde).Q - Specializing to the case where the collinear partner of the soft particle is an initial state particle (i = a ), we have p_a_tilde = xi p_a and 2p_a.Q = Q^2 so that the soft-collinear takes the form 1/(p_r+xi p_a)^2 * xi/y_rQ where y_rQ is the usual Hungarian variable this simplifies to 1/(p_r+p_a)^2 * 1/y_rQ which is exactly the soft collinear as computed *without* tilded variables (i.e. exactly eq.5.29 of 0903.1218) As a result we use exactly the same way of evaluating the counterterms as in honest-to-god colorful. """ # Retrieve alpha_s and mu_r model_param_dict = self.model.get('parameter_dict') alpha_s = model_param_dict['aS'] mu_r = model_param_dict['MU_R'] children = tuple(self.leg_numbers_map[i] for i in sorted(self.leg_numbers_map.keys())) parent = momenta_dict.inv[frozenset(children)] # Perform mapping this_mapping_singular_structure = self.mapping_singular_structure.get_copy() this_mapping_singular_structure.legs = self.get_recoilers(reduced_process, excluded=(parent, )) lower_PS_point, mapping_vars = self.mapping.map_to_lower_multiplicity( higher_PS_point, this_mapping_singular_structure, momenta_dict, compute_jacobian=self.divide_by_jacobian ) reduced_kinematics = (None, lower_PS_point) jacobian = mapping_vars.get('jacobian', 1.) # Include the counterterm only in a part of the phase space # children are the the set of particles that are going unresolved. # Here we have C and S going collinear with S soft. # The parent is the mapped C with a soft mapping, usually refered to as Ctilde. # S is just removed in a soft mapping. # Here S is a single particle but we obtain it as a list soft_children\ # to illustrate how multiple softs would be obtained pCtilde = lower_PS_point[parent] soft_children = [ self.leg_numbers_map[soft_leg_number] for soft_leg_number in self.leg_numbers_map if soft_leg_number>9 ] pS = sum(higher_PS_point[child] for child in soft_children) collinear_final_children = [ self.leg_numbers_map[soft_leg_number] for soft_leg_number in self.leg_numbers_map if 0 < soft_leg_number <= 9 ] if len(collinear_final_children)>0: pCfinal = sum(higher_PS_point[child] for child in collinear_final_children) else: pCfinal = vectors.LorentzVector() pCinitial = higher_PS_point[self.leg_numbers_map[0]] pCmother = pCinitial - pCfinal - pS if self.is_cut(Q=Q, pC=pCmother, pS=pS): return utils.SubtractionCurrentResult.zero( current=current, hel_config=hel_config, reduced_kinematics=('IS_CUT', lower_PS_point)) # Now instantiate what the result will be evaluation = utils.SubtractionCurrentEvaluation({ 'spin_correlations': [None], 'color_correlations': [None], 'reduced_kinematics': [reduced_kinematics], 'values': { } }) # Evaluate kernel kernel_arguments = self.variables(higher_PS_point, pCtilde, children, Q=Q) # kernel_arguments = self.variables(higher_PS_point, pCinitial, children, Q=Q) # There is no need for the ratio of color-averaging factor between the real ME # initial state flavor and the one of the reduced Born ME as they are either both # gluons or both quarks evaluation = self.kernel(evaluation, parent, *kernel_arguments) # Add the normalization factors norm = (8. * math.pi * alpha_s)**(len(soft_children)+len(collinear_final_children)) / ((2.*pCtilde.dot(pS))*pS.square()) norm *= self.factor(Q=Q, pC=pCmother, pS=pS) if self.divide_by_jacobian: norm /= jacobian for k in evaluation['values']: evaluation['values'][k]['finite'] *= norm # Construct and return result result = utils.SubtractionCurrentResult() result.add_result( evaluation, hel_config=hel_config, squared_orders=tuple(sorted(current.get('squared_orders').items()))) return result
def evaluate_subtraction_current(self, current, higher_PS_point=None, momenta_dict=None, reduced_process=None, hel_config=None, Q=None, **opts): if higher_PS_point is None: raise CurrentImplementationError( self.name() + " needs the phase-space points before mapping.") if momenta_dict is None: raise CurrentImplementationError( self.name() + " requires a momentum routing dictionary.") if not hel_config is None: raise CurrentImplementationError( self.name() + " does not support helicity assignment.") if Q is None: raise CurrentImplementationError( self.name() + " requires the total mapping momentum Q.") # Retrieve alpha_s and mu_r model_param_dict = self.model.get('parameter_dict') alpha_s = model_param_dict['aS'] mu_r = model_param_dict['MU_R'] children = tuple(self.leg_numbers_map[i] for i in sorted(self.leg_numbers_map.keys())) parent = momenta_dict.inv[frozenset(children)] # Perform mapping this_mapping_singular_structure = self.mapping_singular_structure.get_copy( ) this_mapping_singular_structure.legs = self.get_recoilers( reduced_process, excluded=(parent, )) lower_PS_point, mapping_vars = self.mapping.map_to_lower_multiplicity( higher_PS_point, this_mapping_singular_structure, momenta_dict, compute_jacobian=self.divide_by_jacobian) reduced_kinematics = (None, lower_PS_point) # Include the counterterm only in a part of the phase space # children are the the set of particles that are going unresolved. # Here we have C and S going collinear with S soft. # The parent is the mapped C with a soft mapping, usually refered to as Ctilde. # S is just removed in a soft mapping. # Here S is a single particle but we obtain it as a list soft_children\ # to illustrate how multiple softs would be obtained pCtilde = lower_PS_point[parent] soft_children = [ self.leg_numbers_map[1], ] pS = sum(higher_PS_point[child] for child in soft_children) if self.is_cut(Q=Q, pC=pCtilde, pS=pS): return utils.SubtractionCurrentResult.zero( current=current, hel_config=hel_config, reduced_kinematics=('IS_CUT', lower_PS_point)) # Now instantiate what the result will be evaluation = utils.SubtractionCurrentEvaluation({ 'spin_correlations': [None], 'color_correlations': [None], 'reduced_kinematics': [ reduced_kinematics, ], 'values': { (0, 0, 0): { 'finite': None } } }) # Evaluate kernel zs = self.variables([pS, pCtilde], Q) z = zs[0] evaluation['values'][( 0, 0, 0)]['finite'] = self.color_charge * 2. * (1. - z) / z # Add the normalization factors s12 = (pCtilde + pS).square() norm = 8. * math.pi * alpha_s / s12 norm *= self.factor(Q=Q, pC=pCtilde, pS=pS) for k in evaluation['values']: evaluation['values'][k]['finite'] *= norm # Construct and return result result = utils.SubtractionCurrentResult() result.add_result(evaluation, hel_config=hel_config, squared_orders=tuple( sorted(current.get('squared_orders').items()))) return result
def evaluate_integrated_current(self, current, PS_point, reduced_process=None, leg_numbers_map=None, hel_config=None, compute_poles=False, **opts): """ Evaluates this current and return the corresponding instance of SubtractionCurrentResult. See documentation of the mother function for more details.""" if not hel_config is None: raise CurrentImplementationError( "Subtraction current implementation " + "%s does not support helicity assignment." % self.__class__.__name__) if leg_numbers_map is None: raise CurrentImplementationError( "Subtraction current implementation " + "%s requires the leg_number_map." % self.__class__.__name__) if reduced_process is None: raise CurrentImplementationError( "Subtraction current implementation " + "%s requires a reduced_process." % self.__class__.__name__) result = utils.SubtractionCurrentResult() ss = current.get('singular_structure').substructures[0] # Retrieve alpha_s and mu_r model_param_dict = self.model.get('parameter_dict') alpha_s = model_param_dict['aS'] mu_r = model_param_dict['MU_R'] # Retrieve kinematic variables from the specified PS point soft_leg_number = ss.legs[0].n # Use the momenta map, in case it has been remapped. # Although for the soft current it's typically not the case soft_leg_number = leg_numbers_map.inv[frozenset([ soft_leg_number, ])] Q = sum([ PS_point[l.get('number')] for l in reduced_process.get_initial_legs() ]) Q_square = Q.square() # Now find all colored leg numbers in the reduced process all_colored_parton_numbers = [] for leg in reduced_process.get('legs'): if self.model.get_particle(leg.get('id')).get('color') == 1: continue all_colored_parton_numbers.append(leg.get('number')) # Now instantiate what the result will be evaluation = utils.SubtractionCurrentEvaluation({ 'spin_correlations': [None], 'color_correlations': [], 'values': {} }) logMuQ = math.log(mu_r**2 / Q_square) prefactor = EpsilonExpansion({0: 1., 1: logMuQ, 2: 0.5 * logMuQ**2}) prefactor *= self.SEpsilon # Now add the normalization factors prefactor *= (alpha_s / (2. * math.pi)) prefactor.truncate(min_power=-2, max_power=2) #Virtuality cut in the integration y_0 = 0.5 color_correlation_index = 0 # Now loop over the colored parton number pairs (a,b) # and add the corresponding contributions to this current for i, a in enumerate(all_colored_parton_numbers): # Use the symmetry of the color correlation and soft current (a,b) <-> (b,a) for b in all_colored_parton_numbers[i + 1:]: evaluation['color_correlations'].append(((a, b), )) # We multiply by a factor 2. because we symmetrized the sum below value = prefactor * 2. pa = PS_point[a] pb = PS_point[b] Y = (pa.dot(pb) * Q_square) / (2. * Q.dot(pa) * Q.dot(pb)) finite_part = HE.SoftFF_Finite_Gabor_DIVJAC_NOD0(y_0, Y) value *= EpsilonExpansion({ 0: finite_part, -1: math.log(Y), -2: 0. }) # Truncate expansion so as to keep only relevant terms value.truncate(min_power=-2, max_power=0) evaluation['values'][( 0, color_correlation_index)] = value.to_human_readable_dict() color_correlation_index += 1 result.add_result(evaluation, hel_config=hel_config, squared_orders=tuple( sorted(current.get('squared_orders').items()))) return result
def evaluate_subtraction_current(self, current, higher_PS_point=None, lower_PS_point=None, leg_numbers_map=None, reduced_process=None, hel_config=None, Q=None, **opts): if higher_PS_point is None or lower_PS_point is None: raise CurrentImplementationError( self.name() + " needs the phase-space points before and after mapping.") if leg_numbers_map is None: raise CurrentImplementationError( self.name() + " requires a leg numbers map, i.e. a momentum dictionary.") if reduced_process is None: raise CurrentImplementationError(self.name() + " requires a reduced_process.") if not hel_config is None: raise CurrentImplementationError( self.name() + " does not support helicity assignment.") if Q is None: raise CurrentImplementationError( self.name() + " requires the total mapping momentum Q.") # Retrieve alpha_s and mu_r model_param_dict = self.model.get('parameter_dict') alpha_s = model_param_dict['aS'] mu_r = model_param_dict['MU_R'] # Include the counterterm only in a part of the phase space children = self.get_sorted_children(current, self.model) parent = leg_numbers_map.inv[frozenset(children)] pC = sum(higher_PS_point[child] for child in children) qC = lower_PS_point[parent] if self.is_cut(Q=Q, pC=pC): return utils.SubtractionCurrentResult.zero(current=current, hel_config=hel_config) # Evaluate collinear subtracted kernel zs, kTs = self.variables(higher_PS_point, qC, children, Q=Q) pr = higher_PS_point[children[0]] ps = higher_PS_point[children[1]] pi = higher_PS_point[children[2]] sir = 2 * pi.dot(pr) sis = 2 * pi.dot(ps) srs = 2 * pr.dot(ps) evaluation = self.evaluate_kernel(zs, kTs, parent) ker = 0 misc.sprint(srs, sir, sis) ker += 2 * self.C123_kernel(zs[0], zs[1], zs[2], srs, sir, sis, sir + sis + srs) ker -= 2 * self.C123S12_kernel(zs[0], zs[1], zs[2], srs, sir, sis, sir + sis + srs) ker -= self.C123C12_kernel(higher_PS_point, lower_PS_point[parent], children, Q=Q) ker += self.C123S12C12_kernel(higher_PS_point, lower_PS_point[parent], children, Q=Q) evaluation['values'][(0, 0)]['finite'] += 0.5 * self.CF * self.TR * ker # Find all colored leg numbers except for the parent in the reduced process all_colored_parton_numbers = [] for leg in reduced_process.get('legs'): if self.model.get_particle(leg.get('id')).get('color') == 1: continue all_colored_parton_numbers.append(leg.get('number')) color_correlation_index = 1 # Now loop over the colored parton number pairs (parent, k) # and add the corresponding contributions to this current emitter = children[2] for k in all_colored_parton_numbers: spectator = k if k == parent: spectator = children[2] evaluation['color_correlations'].append(((parent, k), )) weight = 0 if k != parent: pk = higher_PS_point[k] sik = 2 * pi.dot(pk) skr = 2 * pk.dot(pr) sks = 2 * pk.dot(ps) weight += self.S12_kernel(sir, sis, sik, skr, sks, srs) weight -= 2 * self.S12C12_kernel( higher_PS_point, children, emitter, spectator, Q=Q) evaluation['values'][(0, color_correlation_index)] = { 'finite': weight } color_correlation_index += 1 # Add the normalization factors norm = (8. * math.pi * alpha_s)**2 norm *= self.factor(Q=Q, pC=pC, qC=qC) for k in evaluation['values']: evaluation['values'][k]['finite'] *= norm # Construct and return result result = utils.SubtractionCurrentResult() result.add_result(evaluation, hel_config=hel_config, squared_orders=tuple( sorted(current.get('squared_orders').items()))) return result