From fcd8218b6913a895db7016d994c45e5f5cf58191 Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 00:02:39 +0200 Subject: [PATCH 01/39] optimise pure gluon amplitudes by unrolling the 4-gluon vertex Each colour structure of the four gluon vertex carries exactly the same colour factor as the diagram obtained by splitting that vertex into two cubic ones, so the two can be summed before the colour algebra is applied. Verified against the colour algebra for g g > N g, N=2..5: 3/30/405/6300 links, every one landing on a single cubic diagram, and the merged count matching (2n-5)!! throughout. Generation now runs with the quartic vertex replaced by two cubic vertices joined by an auxiliary line, and puts them back together afterwards. Since the from_group rule picks the canonical decomposition from the topology alone, never from which particle sits on a line, the diagram carrying the auxiliary line is rooted exactly like the cubic one it has to be summed with, and shares every current except that line. Partner coverage goes from 30/60 to 405/405 at six gluons. The recovered vertex only carries the colour structure the two cubic vertices reproduce, which Vertex now records. Which structure that is depends on the order ALOHA receives the legs, so it is settled against sorted_mothers rather than on the generated diagram. g g > g g g 33 -> 15 wavefunctions, ~1.42x g g > g g g g 111 -> 81 wavefunctions, ~1.12x The quartic amplitudes are also summed into their cubic partner, which shrinks the JAMP block from 1091 to 697 lines at six gluons. That one costs nothing at runtime: the JAMP optimiser was already finding those pairs. |M|^2 is unchanged, to the last bit at four and five gluons and to one ulp at six where the summation order differs. All of it is behind MG_MERGE_QUARTIC, off by default. Co-Authored-By: Claude Opus 5 --- madgraph/__init__.py | 6 + madgraph/core/base_objects.py | 25 +- madgraph/core/color_amp.py | 8 +- madgraph/core/diagram_generation.py | 637 +++++++++++++++++- madgraph/core/helas_objects.py | 125 +++- madgraph/iolibs/helas_call_writers.py | 37 + tests/unit_tests/core/test_base_objects.py | 8 +- .../core/test_diagram_generation.py | 161 +++++ 8 files changed, 995 insertions(+), 12 deletions(-) diff --git a/madgraph/__init__.py b/madgraph/__init__.py index 0d17042f0d..e4c7ffc3e9 100755 --- a/madgraph/__init__.py +++ b/madgraph/__init__.py @@ -60,4 +60,10 @@ class aMCatNLOError(MadGraph5Error): ordering = True else: ordering = False + +# Sum the quartic gluon contributions into the cubic amplitude carrying the +# same colour factor, see HelasMatrixElement.get_quartic_amplitude_merges. +# Off by default while the optimisation is being benchmarked. +merge_quartic_vertices = os.environ.get('MG_MERGE_QUARTIC', '') not in \ + ('', '0', 'False') diff --git a/madgraph/core/base_objects.py b/madgraph/core/base_objects.py index a43e58fad7..c9d4f2e641 100755 --- a/madgraph/core/base_objects.py +++ b/madgraph/core/base_objects.py @@ -2979,8 +2979,8 @@ class Vertex(PhysicsObject): """Vertex: list of legs (ordered), id (Interaction) """ - sorted_keys = ['id', 'legs'] - + sorted_keys = ['id', 'legs', 'color_key', 'aux_pair'] + # This sets what are the ID's of the vertices that must be ignored for the # purpose of the multi-channeling. 0 and -1 are ID's of various technical # vertices which have no relevance from the perspective of the diagram @@ -3014,6 +3014,19 @@ def default_setup(self): # that it can be easily identified when constructing the DiagramChainLinks. self['id'] = 0 self['legs'] = LegList() + # Restrict the vertex to a single colour structure of its interaction. + # None (the default) means that all of them contribute, which is the + # normal situation. It is set when a quartic vertex has been recovered + # from the two cubic vertices it factorises into, since each such pair + # rebuilds one specific colour structure (see + # diagram_generation.Amplitude.collapse_auxiliary_diagrams). + self['color_key'] = None + # Numbers of the two legs which used to sit on the auxiliary line. + # The colour structure the vertex is restricted to is the one + # separating them, but which structure that is can only be settled + # once the mothers are in the order ALOHA receives them, so the pair + # is carried along and resolved in generate_helas_diagrams. + self['aux_pair'] = None def filter(self, name, value): """Filter for valid vertex property values.""" @@ -3026,6 +3039,14 @@ def filter(self, name, value): if not isinstance(value, LegList): raise self.PhysicsObjectError("%s is not a valid LegList object" % str(value)) + if name == 'color_key': + if value is not None and not isinstance(value, int): + raise self.PhysicsObjectError("%s is not a valid colour key" % str(value)) + + if name == 'aux_pair': + if value is not None and not isinstance(value, tuple): + raise self.PhysicsObjectError("%s is not a valid auxiliary pair" % str(value)) + return True def get_sorted_keys(self): diff --git a/madgraph/core/color_amp.py b/madgraph/core/color_amp.py index 55d5731fef..02aa2df09b 100755 --- a/madgraph/core/color_amp.py +++ b/madgraph/core/color_amp.py @@ -197,10 +197,16 @@ def add_vertex(self, vertex, diagram, model, new_res_dict = {} for i, col_str in \ enumerate(inter_color): - + # Ignore color string if it doesn't correspond to any coupling if i not in inter_indices: continue + + # A vertex rebuilt from the two cubic vertices it factorises into + # only carries the colour structure those two reproduce. + if vertex.get('color_key') is not None and \ + i != vertex.get('color_key'): + continue # Build the new element assert type(col_str) == color_algebra.ColorString diff --git a/madgraph/core/diagram_generation.py b/madgraph/core/diagram_generation.py index 1f239abf5b..bbf031cc6d 100755 --- a/madgraph/core/diagram_generation.py +++ b/madgraph/core/diagram_generation.py @@ -24,11 +24,13 @@ import array import copy +import fractions import itertools import logging import madgraph import madgraph.core.base_objects as base_objects +import madgraph.core.color_algebra as color_algebra import madgraph.various.misc as misc import madgraph.fks.fks_tag as fks_tag from madgraph import InvalidCmd, MadGraph5Error @@ -294,6 +296,10 @@ def vertex_id_from_vertex(vertex, last_vertex, model, ninitial): # return (vertex.get('id'),(),{'PDGs':vertex.get('PDGs')}) return ((vertex.get('id'),vertex.get('loop_tag')),(), {'PDGs':vertex.get('PDGs')}) + elif vertex.get('color_key') is not None: + # a vertex restricted to one colour structure is not the same + # vertex as the unrestricted one, nor as the other restrictions + return ((vertex.get('id'),(vertex.get('color_key'),)),(),{}) else: return ((vertex.get('id'),()),(),{}) @@ -427,6 +433,397 @@ def __str__(self): __repr__ = __str__ +#=============================================================================== +# Unrolling of quartic vertices into pairs of cubic vertices +#=============================================================================== + +class UnrollDiagramTag(DiagramTag): + """DiagramTag which keeps every external leg distinct. + + The default DiagramTag deliberately identifies identical final state + particles, which is what is wanted when comparing different processes. To + recognise a diagram inside its own amplitude we need the leg numbers, so + that e.g. the t- and u-channel of g g > g g do not collide.""" + + @staticmethod + def link_from_leg(leg, model): + return [((leg.get('id'), leg.get('number')), leg.get('number'))] + + +def get_unrollable_quartic_vertices(model): + """Find the quartic interactions which factorise into two cubic ones. + + A quartic vertex qualifies when its four legs carry the same + self-conjugate particle and each of its colour structures is a product of + two structure constants sharing a single summed index -- the four gluon + vertex being the canonical example. Such a colour structure splits the + four colour indices into two pairs, and that splitting is precisely the + one produced by two cubic vertices joined by an internal line. + + Returns {quartic_id: (cubic_id, pairings)} where pairings[icolor] is the + pair of 2-tuples of colour index positions separated by the summed index. + """ + + try: + return model._unrollable_quartic_vertices + except AttributeError: + pass + + # Cubic candidates: three identical legs with a single f(0,1,2) structure + cubic_by_pdg = {} + for inter in model.get('interactions'): + parts = inter.get('particles') + if len(parts) != 3: + continue + pdgs = misc.make_unique([p.get_pdg_code() for p in parts]) + if len(pdgs) != 1: + continue + color = inter.get('color') + if len(color) != 1 or len(color[0]) != 1: + continue + if not isinstance(color[0][0], color_algebra.f) or \ + sorted(color[0][0]) != [0, 1, 2]: + continue + cubic_by_pdg[pdgs[0]] = inter.get('id') + + res = {} + for inter in model.get('interactions'): + parts = inter.get('particles') + if len(parts) != 4: + continue + pdgs = misc.make_unique([p.get_pdg_code() for p in parts]) + if len(pdgs) != 1 or pdgs[0] not in cubic_by_pdg: + continue + pairings = [] + for col_str in inter.get('color'): + pairing = _f_pair_split(col_str) + if pairing is None: + break + pairings.append(pairing) + else: + if pairings: + res[inter.get('id')] = (cubic_by_pdg[pdgs[0]], pairings) + + try: + model._unrollable_quartic_vertices = res + except AttributeError: + pass + return res + + +def pinned_color_key(helas_object): + """Colour structure a reconstructed vertex has to be restricted to. + + With merge_quartic_vertices the quartic vertices are recovered from the + two cubic ones they factorise into and therefore carry a single colour + structure. The diagram rebuilt from the helas objects has to say so, + otherwise colorize() expands all of them and the colour chains no longer + match the amplitudes that were actually generated.""" + + if not madgraph.merge_quartic_vertices: + return None + model = getattr(helas_object, 'model', None) + if model is None: + return None + if helas_object.get('interaction_id') in \ + get_unrollable_quartic_vertices(model): + return helas_object.get('color_key') + return None + + +def _f_pair_split(col_str): + """If col_str is f(..)*f(..) with a single shared summed index and the + four remaining indices being 0,1,2,3, return the two pairs of external + colour index positions it separates, otherwise None.""" + + if len(col_str) != 2 or not all(isinstance(obj, color_algebra.f) + for obj in col_str): + return None + shared = [i for i in col_str[0] if i in col_str[1]] + if len(shared) != 1 or shared[0] >= 0: + return None + pairs = tuple(tuple(sorted(i for i in obj if i != shared[0])) + for obj in col_str) + if sorted(pairs[0] + pairs[1]) != [0, 1, 2, 3]: + return None + return pairs + + +AUXILIARY_PDG_OFFSET = 9000000 + + +def get_auxiliary_model(model): + """Return a copy of model where every unrollable quartic vertex has been + replaced by two cubic vertices joined by an auxiliary line. + + Generating with this model gives one diagram per colour structure of the + quartic vertex, and -- this is the point -- the diagram carrying the + auxiliary line has exactly the same topology, and therefore exactly the + same decomposition, as the purely cubic diagram it has to be summed with. + The 'from_group' rule which makes that decomposition canonical only looks + at the topology, never at which particle sits on a line, so the two are + rooted identically and every current except the auxiliary line itself is + shared. The auxiliary lines are removed again by + Amplitude.collapse_auxiliary_diagrams before the diagrams are used. + + Returns (model, {auxiliary pdg: (quartic id, cubic id, pairings)}) or + (model, {}) if there is nothing to do. + + Note that copy.deepcopy must not be used on colour structures: ColorObject + derives from array.array and deepcopy silently turns it into a plain array. + """ + + unrollable = get_unrollable_quartic_vertices(model) + if not unrollable: + return model, {} + + particles = base_objects.ParticleList(model.get('particles')) + interactions = base_objects.InteractionList( + [inter for inter in model.get('interactions') + if inter.get('id') not in unrollable]) + next_id = max(inter.get('id') for inter in model.get('interactions')) + 1 + + auxiliaries = {} + for quartic_id, (cubic_id, pairings) in unrollable.items(): + quartic = model.get_interaction(quartic_id) + partner = quartic.get('particles')[0] + aux_pdg = AUXILIARY_PDG_OFFSET + partner.get_pdg_code() + auxiliary = base_objects.Particle({ + 'name': 'aux%d' % partner.get_pdg_code(), + 'antiname': 'aux%d' % partner.get_pdg_code(), + 'spin': partner.get('spin'), 'color': partner.get('color'), + 'charge': 0., 'mass': 'ZERO', 'width': 'ZERO', + 'pdg_code': aux_pdg, 'line': partner.get('line'), + 'is_part': True, 'self_antipart': True}) + particles.append(auxiliary) + + # the quartic coupling order is shared between the two cubic vertices + orders = dict((order, value // 2) + for order, value in quartic.get('orders').items()) + interactions.append(base_objects.Interaction({ + 'id': next_id, + 'particles': base_objects.ParticleList( + [partner, partner, auxiliary]), + 'color': [color_algebra.ColorString( + [color_algebra.f(0, 1, 2)])], + 'lorentz': model.get_interaction(cubic_id).get('lorentz'), + 'couplings': dict(model.get_interaction(cubic_id).get('couplings')), + 'orders': orders})) + auxiliaries[aux_pdg] = (quartic_id, next_id, pairings) + next_id += 1 + + aux_model = base_objects.Model() + aux_model.set('particles', particles) + aux_model.set('interactions', interactions) + for key in ('name', 'order_hierarchy', 'conserved_charge', + 'coupling_orders', 'expansion_order'): + try: + aux_model.set(key, model.get(key)) + except Exception: + pass + + return aux_model, auxiliaries + + +def colour_index_order(vertex, is_last, model): + """Return the vertex legs in the order in which color_amp.ColorBasis maps + them onto the colour indices of the interaction. + + This mirrors ColorBasis.add_vertex: the outgoing leg of an internal + vertex is flipped to its antiparticle and moved to the front, then the + legs are sorted following the particle order of the interaction. Note + that the sorting can move the outgoing leg away from the front again, so + its position is returned along with the legs. + + Returns (legs, outgoing_position), the position being None for the last + vertex of a diagram, or None if the vertex does not match its + interaction.""" + + inter = model.get_interaction(vertex.get('id')) + if inter is None: + return None + + legs = vertex.get('legs') + entries = [] + for index, leg in enumerate(legs): + part = model.get('particle_dict')[leg.get('id')] + outgoing = index == len(legs) - 1 and not is_last + entries.append((leg, part.get_anti_pdg_code() if outgoing + else part.get_pdg_code(), outgoing)) + + if not is_last: + entries.insert(0, entries.pop(-1)) + + ordered = [] + for pdg in [p.get_pdg_code() for p in inter.get('particles')]: + for index, entry in enumerate(entries): + if entry[1] == pdg: + ordered.append(entries.pop(index)) + break + else: + return None + + out_position = None + for index, entry in enumerate(ordered): + if entry[2]: + out_position = index + + return [entry[0] for entry in ordered], out_position + + +def split_quartic_vertex(vertex, is_last, pairing, cubic_id, model): + """Replace a quartic vertex by the two cubic vertices that the given + colour structure factorises into, joined by a new internal line.""" + + ordered, out_position = colour_index_order(vertex, is_last, model) + first, second = pairing + if not is_last and out_position in first: + # the pair the outgoing leg does not belong to is the one replaced by + # the new internal line + first, second = second, first + + combined = [ordered[i] for i in first] + new_leg = base_objects.Leg({ + 'id': combined[0].get('id'), + 'number': min(leg.get('number') for leg in combined), + 'state': len([l for l in combined if not l.get('state')]) != 1, + 'from_group': True}) + + first_vx = base_objects.Vertex({ + 'legs': base_objects.LegList(combined + [new_leg]), + 'id': cubic_id}) + if is_last: + rest = [ordered[i] for i in second] + [new_leg] + else: + # the outgoing leg has to stay last + rest = [ordered[i] for i in second if i != out_position] + \ + [new_leg, ordered[out_position]] + second_vx = base_objects.Vertex({'legs': base_objects.LegList(rest), + 'id': cubic_id}) + + return [first_vx, second_vx] + + +# Placeholder standing for the single summed index of a factorisable quartic +# colour structure, which is not a leg of the vertex. +_SUMMED = 'summed' + + +def diagram_colour_signature(diagram, model, color_chain, unrollable): + """Canonical signature of the colour string of one colour structure choice. + + Returns (key, coeff), where key identifies the product of colour objects + up to the antisymmetry of the structure constants and coeff collects the + resulting sign together with the rational prefactors. Two contributions + sharing a key have proportional colour factors and can be summed, the + relative weight being the ratio of their coeff. + + Every line is labelled by the set of external legs it separates rather + than by its leg number, so that the signature can be compared between + diagrams which number their internal lines differently. Returns None when + the colour structure is not of a supported form. + """ + + vertices = diagram.get('vertices') + last = len(vertices) - 1 + + # A leg number is reused by the vertex which produces it, so an external + # leg is one consumed while no internal line of that number is alive. + alive = {} + externals = [] + for i, vertex in enumerate(vertices): + legs = vertex.get('legs') + incoming = legs if i == last else legs[:-1] + for leg in incoming: + if alive.pop(leg.get('number'), None) is None: + externals.append(leg.get('number')) + if i != last: + alive[legs[-1].get('number')] = True + externals = frozenset(externals) + if not externals: + return None + reference = min(externals) + + def normalise(side): + """Root independent label of the line splitting side from its rest.""" + return side if reference not in side else externals - side + + factors = [] + coeff = fractions.Fraction(1, 1) + imaginary = False + live = {} + for i, vertex in enumerate(vertices): + inter = model.get_interaction(vertex.get('id')) + if inter is None: + return None + order = colour_index_order(vertex, i == last, model) + if order is None: + return None + ordered, out_position = order + sides = [None] * len(ordered) + below = frozenset() + # the outgoing leg is only known once all the incoming ones are read, + # since a vertex reuses the smallest incoming leg number for it + for pos in range(len(ordered)): + if pos == out_position: + continue + number = ordered[pos].get('number') + side = live.pop(number, None) + if side is None: + side = frozenset([number]) + sides[pos] = side + below = below | side + if out_position is not None: + # the outgoing leg carries everything that is not below it + sides[out_position] = externals - below + live[ordered[out_position].get('number')] = below + + labels = dict(enumerate(normalise(side) for side in sides)) + if vertex.get('id') in unrollable: + pairing = unrollable[vertex.get('id')][1][color_chain[i]] + labels[_SUMMED] = normalise(sides[pairing[0][0]] | + sides[pairing[0][1]]) + + if not inter.get('color'): + continue + col_str = inter.get('color')[color_chain[i]] + coeff *= col_str.coeff + imaginary ^= col_str.is_imaginary + for obj in col_str: + try: + indices = [labels[j if j >= 0 else _SUMMED] for j in obj] + except KeyError: + return None + if isinstance(obj, color_algebra.f): + # totally antisymmetric: sort and keep track of the parity + order = sorted(range(len(indices)), + key=lambda k: sorted(indices[k])) + coeff *= _permutation_sign(order) + indices = [indices[k] for k in order] + factors.append((obj.__class__.__name__, + tuple(tuple(sorted(index)) for index in indices))) + + return (tuple(sorted(factors)), imaginary), coeff + + +def _permutation_sign(order): + """Signature of a permutation given as a list of positions.""" + + sign = 1 + seen = [False] * len(order) + for start in range(len(order)): + if seen[start]: + continue + length = 0 + pos = start + while not seen[pos]: + seen[pos] = True + pos = order[pos] + length += 1 + if length % 2 == 0: + sign = -sign + return sign + #=============================================================================== # Amplitude #=============================================================================== @@ -580,8 +977,31 @@ def generate_diagrams(self, returndiag=False, diagram_filter=False): "particles are missing in model: %s" % model.get('particles') assert model.get('interactions'), \ - "interactions are missing in model" - + "interactions are missing in model" + + # Generate with every unrollable quartic vertex split into the two + # cubic vertices it factorises into, then put them back together. This + # gives one diagram per colour structure of the quartic vertex, each + # sharing its topology -- and hence its currents -- with the purely + # cubic diagram it has to be summed with. The auxiliary model has no + # unrollable vertex left, so the recursion below stops immediately. + if madgraph.merge_quartic_vertices and \ + not process.get('is_decay_chain'): + aux_model, auxiliaries = get_auxiliary_model(model) + if auxiliaries: + aux_process = copy.copy(process) + aux_process.set('model', aux_model) + aux_amplitude = Amplitude() + aux_amplitude.set('process', aux_process) + success = aux_amplitude.generate_diagrams( + diagram_filter=diagram_filter) + res = self.collapse_auxiliary_diagrams( + aux_amplitude.get('diagrams'), auxiliaries) + self.trim_diagrams(diaglist=res) + if returndiag: + return success, res + self['diagrams'] = res + return success res = base_objects.DiagramList() # First check that the number of fermions is even @@ -944,9 +1364,220 @@ def remove_diag(diag, model=None): return res + def unroll_quartic_vertices(self, diaglist=None): + """Link every quartic vertex contribution to the cubic diagram it + merges with. + + Each colour structure of an unrollable quartic vertex (see + get_unrollable_quartic_vertices) splits its four legs into two pairs, + which is exactly what two cubic vertices joined by an internal line + do. Replacing every quartic vertex of a diagram by that pair of cubic + vertices therefore turns it into a diagram already present in the + amplitude, and the two carry the same colour factor up to a rational + coefficient. Their amplitudes can hence be summed before the colour + algebra is applied. + + Returns {(diagram_index, colour_chain): (target_index, coeff)} where + colour_chain follows the convention of color_amp.ColorBasis.colorize + (one colour structure index per vertex) and the amplitude of the + source is coeff times a contribution to the target diagram. Diagrams + without any quartic vertex are left out. + + To line the result up with HelasAmplitude, call this on the + *reconstructed* amplitude, HelasMatrixElement.get_base_amplitude(), + and not on the amplitude the matrix element was built from. That is + the one helas_objects itself colorizes, and the vertex order of the + reconstructed diagrams -- hence the position of a colour structure + index inside the chain -- can differ from the generated ones. The two + happen to agree up to six gluons and start to differ at seven. + """ + + model = self.get('process').get('model') + if diaglist is None: + diaglist = self.get('diagrams') + + unrollable = get_unrollable_quartic_vertices(model) + if not unrollable: + return {} + + quartic_positions = [] + for diag in diaglist: + quartic_positions.append([i for i, vx in + enumerate(diag.get('vertices')) + if vx.get('id') in unrollable]) + if not any(quartic_positions): + return {} + + ninitial = self.get_ninitial() + # Diagrams free of quartic vertices are the possible merge targets + target_index = {} + for i, diag in enumerate(diaglist): + if quartic_positions[i]: + continue + target_index[str(UnrollDiagramTag(diag, model, ninitial))] = i + + res = {} + for i, diag in enumerate(diaglist): + positions = quartic_positions[i] + if not positions: + continue + # only the colour structures which carry a coupling contribute, + # matching what color_amp.ColorBasis.colorize keeps, and a vertex + # pinned to one structure contributes only that one + allowed = [] + for position in positions: + vertex = diag.get('vertices')[position] + if vertex.get('color_key') is not None: + allowed.append([vertex.get('color_key')]) + else: + allowed.append(sorted(misc.make_unique( + [key[0] for key in model.get_interaction( + vertex.get('id')).get('couplings')]))) + for keys in itertools.product(*allowed): + choice = dict(zip(positions, keys)) + unrolled = self.unrolled_diagram(diag, choice, unrollable) + try: + target = target_index[ + str(UnrollDiagramTag(unrolled, model, ninitial))] + except KeyError: + # No cubic partner: the merge is not available, which can + # happen when the partner was removed by a diagram filter + # or by a forbidden s-channel. + continue + chain = tuple(choice.get(p, 0) + for p in range(len(diag.get('vertices')))) + source_sig = diagram_colour_signature(diag, model, chain, + unrollable) + target_chain = (0,) * len(diaglist[target].get('vertices')) + target_sig = diagram_colour_signature(diaglist[target], model, + target_chain, unrollable) + if source_sig is None or target_sig is None or \ + source_sig[0] != target_sig[0]: + continue + res[(i, chain)] = (target, source_sig[1] / target_sig[1]) + + return res + + def collapse_auxiliary_diagrams(self, diaglist, auxiliaries): + """Turn every auxiliary line back into the quartic vertex it stands for. + + The two cubic vertices sharing an auxiliary line rebuild one specific + colour structure of the quartic vertex, so the recovered vertex is + pinned to that structure through its 'color_key'. The legs are ordered + so that the pair which used to sit on the auxiliary line lands on the + colour indices that structure separates. + """ + + if not auxiliaries: + return diaglist + + res = diaglist.__class__() + for diagram in diaglist: + vertices = diagram.get('vertices') + last = len(vertices) - 1 + # an auxiliary line is produced by the vertex whose outgoing leg + # carries it, and consumed by the one having it as an incoming leg + produced = {} + for i, vertex in enumerate(vertices): + if i == last: + continue + pdg = vertex.get('legs')[-1].get('id') + if pdg in auxiliaries: + produced[vertex.get('legs')[-1].get('number')] = (i, pdg) + + if not produced: + res.append(diagram) + continue + + collapsed = {} + for i, vertex in enumerate(vertices): + incoming = vertex.get('legs') if i == last \ + else vertex.get('legs')[:-1] + for position, leg in enumerate(incoming): + if leg.get('id') not in auxiliaries: + continue + collapsed[i] = (produced[leg.get('number')][0], position, + auxiliaries[leg.get('id')]) + + new_vertices = base_objects.VertexList() + for i, vertex in enumerate(vertices): + if i in [source for source, _, _ in collapsed.values()]: + continue # the producer disappears into the consumer + if i not in collapsed: + new_vertices.append(vertex) + continue + source, position, (quartic_id, _, pairings) = collapsed[i] + pair = list(vertices[source].get('legs')[:-1]) + rest = [leg for j, leg in enumerate( + vertex.get('legs') if i == last + else vertex.get('legs')[:-1]) if j != position] + new_vertices.append(self.collapsed_vertex( + pair, rest, None if i == last else vertex.get('legs')[-1], + quartic_id, pairings)) + res.append(base_objects.Diagram({'vertices': new_vertices})) + + return res + + def collapsed_vertex(self, pair, rest, outgoing, quartic_id, pairings): + """Build the quartic vertex standing for an auxiliary line separating + pair from rest, pinned to the colour structure which does that split.""" + + # The incoming legs are kept in a canonical order rather than in an + # order chosen to suit the pair: the three vertices recovered from the + # three pairings of the same quartic vertex have to differ by their + # colour structure only. Reordering them instead would make them the + # same vertex once the helas mothers are sorted, and one structure + # would be counted three times. + incoming = sorted(rest + pair, key=lambda leg: leg.get('number')) + legs = base_objects.LegList(incoming) + if outgoing is not None: + legs.append(outgoing) + vertex = base_objects.Vertex({'legs': legs, 'id': quartic_id}) + + # An unrollable quartic vertex has four legs of the same particle, so + # ordering on the interaction particles leaves them alone and the + # colour index order is just the outgoing leg moved to the front. + offset = 0 if outgoing is None else 1 + numbers = [leg.get('number') for leg in incoming] + positions = frozenset(offset + numbers.index(leg.get('number')) + for leg in pair) + for key, pairing in enumerate(pairings): + if frozenset(pairing[0]) == positions or \ + frozenset(pairing[1]) == positions: + # This key labels the pairing in the leg order used here, which + # is enough to keep the three recovered vertices distinct. The + # key actually used is settled against the helas mother order + # by HelasMatrixElement.resolve_auxiliary_color_key. + vertex.set('color_key', key) + vertex.set('aux_pair', + tuple(leg.get('number') for leg in pair)) + return vertex + + raise MadGraph5Error( + 'No colour structure of interaction %d separates the auxiliary ' + 'pair' % quartic_id) + + def unrolled_diagram(self, diagram, choice, unrollable): + """Return a copy of diagram where the quartic vertices listed in + choice (position -> colour structure index) have been replaced by the + two cubic vertices that colour structure factorises into.""" + + model = self.get('process').get('model') + vertices = base_objects.VertexList() + for i, vertex in enumerate(diagram.get('vertices')): + if i not in choice: + vertices.append(vertex) + continue + cubic_id, pairings = unrollable[vertex.get('id')] + vertices.extend(split_quartic_vertex( + vertex, i == len(diagram.get('vertices')) - 1, + pairings[choice[i]], cubic_id, model)) + + return base_objects.Diagram({'vertices': vertices}) + def apply_4gluon_specials(self, diag_list): - res = diag_list.__class__() + res = diag_list.__class__() for diag in diag_list: keep = True for vertex in diag.get('vertices'): diff --git a/madgraph/core/helas_objects.py b/madgraph/core/helas_objects.py index 46d3b015e7..802e9cc816 100755 --- a/madgraph/core/helas_objects.py +++ b/madgraph/core/helas_objects.py @@ -2054,7 +2054,8 @@ def get_base_vertex(self, wf_dict, vx_list = [], optimization = 1): vertex = base_objects.Vertex({ 'id': self.get('interaction_id'), - 'legs': legs}) + 'legs': legs, + 'color_key': diagram_generation.pinned_color_key(self)}) return vertex @@ -3411,7 +3412,8 @@ def get_base_vertex(self, wf_dict, vx_list = [], optimization = 1): return base_objects.Vertex({ 'id': self.get('interaction_id'), - 'legs': legs}) + 'legs': legs, + 'color_key': diagram_generation.pinned_color_key(self)}) def get_s_and_t_channels(self, ninitial, model, new_pdg, reverse_t_ch = False): """Returns two lists of vertices corresponding to the s- and @@ -3997,6 +3999,9 @@ def default_setup(self): self._flavor_populated = False self._flavor_allow_trimming = False self._flavor_trimmed = False + # Cache for get_quartic_amplitude_merges(), needed both by the helas + # calls and by the colour amplitudes. Runtime only, like the above. + self.quartic_amplitude_merges = None def filter(self, name, value): """Filter for valid diagram property values.""" @@ -4227,6 +4232,15 @@ def generate_helas_diagrams(self, amplitude, optimization=1,decay_ids=[]): done_color = {} # store link to color for coupl_key in sorted(inter.get('couplings').keys()): color = coupl_key[0] + # a vertex rebuilt from two cubic vertices only carries + # the colour structure those two reproduce + if vertex.get('color_key') is not None: + probe = HelasWavefunction(last_leg, + vertex.get('id'), model) + probe.set('mothers', mothers) + if color != self.resolve_auxiliary_color_key( + probe, vertex, model): + continue if color in done_color: wf = done_color[color] wf.get('coupling').append(inter.get('couplings')[coupl_key]) @@ -4328,6 +4342,14 @@ def generate_helas_diagrams(self, amplitude, optimization=1,decay_ids=[]): done_color = {} for i, coupl_key in enumerate(keys): color = coupl_key[0] + # a vertex rebuilt from two cubic vertices only carries + # the colour structure those two reproduce + if inter and lastvx.get('color_key') is not None: + probe = HelasAmplitude(lastvx, model) + probe.set('mothers', mothers) + if color != self.resolve_auxiliary_color_key( + probe, lastvx, model): + continue if inter and color in list(done_color.keys()): amp = done_color[color] amp.get('coupling').append(inter.get('couplings')[coupl_key]) @@ -6107,13 +6129,108 @@ def generate_color_amplitudes(self, color_basis, diagrams): return col_amp_list + + @staticmethod + def resolve_auxiliary_color_key(candidate, vertex, model): + """Colour structure a recovered quartic vertex is restricted to. + + The vertex was rebuilt from two cubic vertices sharing an auxiliary + line, so it only carries the colour structure separating the pair that + used to sit on that line. Which structure that is depends on the order + in which ALOHA receives the legs, so it can only be settled here, + against sorted_mothers, and not on the generated diagram.""" + + pair = vertex.get('aux_pair') + pairings = diagram_generation.get_unrollable_quartic_vertices( + model).get(vertex.get('id'), (None, None))[1] + if pair is None or pairings is None: + return vertex.get('color_key') + + mothers = HelasMatrixElement.sorted_mothers(candidate) + if isinstance(candidate, HelasWavefunction): + outgoing = candidate.find_outgoing_number() - 1 + slots = [i for i in range(len(mothers) + 1) if i != outgoing] + else: + slots = list(range(len(mothers))) + wanted = frozenset(slots[i] for i, mother in enumerate(mothers) + if mother.get('number_external') in pair) + for key, pairing in enumerate(pairings): + if frozenset(pairing[0]) == wanted or \ + frozenset(pairing[1]) == wanted: + return key + return vertex.get('color_key') + def get_color_amplitudes(self): """Return a list of (coefficient, amplitude number) lists, corresponding to the JAMPs for this matrix element. The coefficients are given in the format (fermion factor, color coeff (frac), imaginary, Nc power).""" - - return self.generate_color_amplitudes(self['color_basis'],self['diagrams']) + + col_amps = self.generate_color_amplitudes(self['color_basis'], + self['diagrams']) + merges = self.get_quartic_amplitude_merges() + if not merges: + return col_amps + # These have been summed into their partner by GET_AMP already, so + # they must not enter the JAMPs a second time. + return [[entry for entry in col_amp if entry[1] not in merges] + for col_amp in col_amps] + + def get_quartic_amplitude_merges(self): + """Return {amplitude number: (target number, coefficient)} for the + quartic gluon contributions which can be summed into another + amplitude. + + Each colour structure of a four gluon vertex carries the same colour + factor as the diagram obtained by splitting that vertex into two cubic + ones, see diagram_generation.Amplitude.unroll_quartic_vertices, so the + two amplitudes may be added before the colour algebra is applied. + Doing so here keeps the JAMPs -- and hence the work of the JAMP + optimiser -- proportional to the number of cubic diagrams rather than + to the number of amplitudes. + + The result is cached, since it is needed both when writing the helas + calls and when building the colour amplitudes. + """ + + if self.quartic_amplitude_merges is None: + self.quartic_amplitude_merges = self.compute_quartic_amplitude_merges() + return self.quartic_amplitude_merges + + def compute_quartic_amplitude_merges(self): + """Work out the amplitude merges, see get_quartic_amplitude_merges.""" + + if not madgraph.merge_quartic_vertices: + return {} + # colorize() is applied to the reconstructed amplitude, so this is the + # one whose colour chains line up with our 'color_indices' + base = self.get('base_amplitude') + links = base.unroll_quartic_vertices() + if not links: + return {} + + numbers = {} + for diagram in self.get('diagrams'): + for amplitude in diagram.get('amplitudes'): + numbers[(diagram.get('number') - 1, + tuple(amplitude.get('color_indices')))] = \ + amplitude.get('number') + + res = {} + for source, (target, coeff) in links.items(): + target_chain = (0,) * \ + len(base.get('diagrams')[target].get('vertices')) + try: + res[numbers[source]] = (numbers[(target, target_chain)], coeff) + except KeyError: + # no amplitude for one of the two: leave them alone + continue + + # a merged amplitude must never itself be merged away, otherwise the + # contributions it absorbed would be lost + targets = set(target for target, _ in res.values()) + return dict((source, value) for source, value in res.items() + if source not in targets) def sort_split_orders(self, split_orders): """ Sort the 'split_orders' list given in argument so that the orders of diff --git a/madgraph/iolibs/helas_call_writers.py b/madgraph/iolibs/helas_call_writers.py index 2910e6a66d..fecc12effd 100755 --- a/madgraph/iolibs/helas_call_writers.py +++ b/madgraph/iolibs/helas_call_writers.py @@ -242,8 +242,17 @@ def get_matrix_element_calls(self, matrix_element): for amplitude in diagram.get('amplitudes'): res.append(self.get_amplitude_call(amplitude)) + res.extend(self.get_amplitude_merge_lines(matrix_element)) + return res + def get_amplitude_merge_lines(self, matrix_element): + """Lines summing the quartic contributions into the amplitude which + carries the same colour factor. Only the Fortran writer implements + this, see FortranUFOHelasCallWriter.""" + + return [] + def get_wavefunction_calls(self, wavefunctions): """Return a list of strings, corresponding to the Helas calls for the matrix element""" @@ -1027,6 +1036,34 @@ class FortranUFOHelasCallWriter(UFOHelasCallWriter): mp_prefix = check_param_card.ParamCard.mp_prefix + def get_amplitude_merge_lines(self, matrix_element): + """Sum every quartic contribution into the amplitude carrying the + same colour factor. + + The two share a colour factor up to a rational coefficient, so adding + them here lets the JAMPs run over the cubic diagrams only, which is + what the JAMP optimiser then has to work with. The amplitudes summed + away are dropped from the colour amplitudes by + HelasMatrixElement.get_color_amplitudes.""" + + merges = matrix_element.get_quartic_amplitude_merges() + if not merges: + return [] + + res = ['# Sum the quartic contributions into their cubic partner'] + for source in sorted(merges): + target, coeff = merges[source] + if coeff == 1: + res.append('AMP(%d) = AMP(%d) + AMP(%d)' % + (target, target, source)) + elif coeff == -1: + res.append('AMP(%d) = AMP(%d) - AMP(%d)' % + (target, target, source)) + else: + res.append('AMP(%d) = AMP(%d) + (%.15e)*AMP(%d)' % + (target, target, float(coeff), source)) + return res + def __init__(self, argument={}, hel_sum = False, options={}): """Allow generating a HelasCallWriter from a Model.The hel_sum argument specifies if amplitude and wavefunctions must be stored specifying the diff --git a/tests/unit_tests/core/test_base_objects.py b/tests/unit_tests/core/test_base_objects.py index 65d99dce7c..0dfba047c8 100755 --- a/tests/unit_tests/core/test_base_objects.py +++ b/tests/unit_tests/core/test_base_objects.py @@ -1473,7 +1473,9 @@ class VertexTest(unittest.TestCase): def setUp(self): self.mydict = {'id':3, - 'legs':self.myleglist} + 'legs':self.myleglist, + 'color_key':None, + 'aux_pair':None} self.myvertex = base_objects.Vertex(self.mydict) @@ -1547,7 +1549,9 @@ def test_representation(self): goal = "{\n" goal = goal + " \'id\': 3,\n" - goal = goal + " \'legs\': %s\n}" % repr(self.myleglist) + goal = goal + " \'legs\': %s,\n" % repr(self.myleglist) + goal = goal + " \'color_key\': None,\n" + goal = goal + " \'aux_pair\': None\n}" self.assertEqual(goal, str(self.myvertex)) diff --git a/tests/unit_tests/core/test_diagram_generation.py b/tests/unit_tests/core/test_diagram_generation.py index 729c50ce3b..cdb7bc2908 100755 --- a/tests/unit_tests/core/test_diagram_generation.py +++ b/tests/unit_tests/core/test_diagram_generation.py @@ -17,6 +17,7 @@ from __future__ import absolute_import import copy +import fractions import itertools import logging import math @@ -25,6 +26,7 @@ import tests.unit_tests as unittest import madgraph.core.base_objects as base_objects +import madgraph.core.color_amp as color_amp import madgraph.core.diagram_generation as diagram_generation import models.import_ufo as import_ufo from madgraph import MadGraph5Error, InvalidCmd @@ -3893,3 +3895,162 @@ def test_diagram_tag_to_diagram_uux_nglue(self): self.assertEqual(dtag, diagram_generation.DiagramTag(\ dtag.diagram_from_tag(self.base_model))) + +#=============================================================================== +# TestQuarticUnrolling +#=============================================================================== +class TestQuarticUnrolling(unittest.TestCase): + """Test the unrolling of quartic vertices into pairs of cubic ones""" + + def setUp(self): + self.base_model = import_ufo.import_model('sm') + + def make_amplitude(self, initial, final, orders=None): + myleglist = base_objects.LegList( + [base_objects.Leg({'id':pdg, 'state':False}) for pdg in initial] + + [base_objects.Leg({'id':pdg, 'state':True}) for pdg in final]) + mydict = {'legs':myleglist, 'model':self.base_model} + if orders: + mydict['orders'] = orders + return diagram_generation.Amplitude(base_objects.Process(mydict)) + + def colour_directions(self, amplitude): + """Return {(diagram, colour chain): (direction, norm)} where direction + is the colour vector of that contribution normalised to its first non + zero entry. Two contributions can be summed exactly when they share a + direction, the relative weight being the ratio of their norms. This is + computed from the colour algebra and is completely independent from + the unrolling being tested.""" + + basis = color_amp.ColorBasis() + basis.build(amplitude) + components = {} + for index, key in enumerate(sorted(basis.keys())): + for (diag, chain, coeff, imag, nc, loop_nc) in basis[key]: + components.setdefault((diag, chain), {})[index] = \ + (fractions.Fraction(coeff), imag, nc, loop_nc) + + res = {} + for piece, entries in components.items(): + first = min(entries) + norm, imag, nc, loop_nc = entries[first] + res[piece] = (tuple(sorted( + (i, c / norm, m ^ imag, n - nc, l - loop_nc) + for i, (c, m, n, l) in entries.items())), norm) + return res + + def check_process(self, initial, final, nlink, orders=None): + """Every link must reproduce the colour algebra, and every quartic + contribution must be linked to exactly one cubic diagram.""" + + amplitude = self.make_amplitude(initial, final, orders) + links = amplitude.unroll_quartic_vertices() + directions = self.colour_directions(amplitude) + diagrams = amplitude.get('diagrams') + + self.assertEqual(len(links), nlink) + + for (diag, chain), (target, coeff) in links.items(): + target_chain = (0,) * len(diagrams[target].get('vertices')) + source_dir, source_norm = directions[(diag, chain)] + target_dir, target_norm = directions[(target, target_chain)] + # same colour direction, and the coefficient is the relative weight + self.assertEqual(source_dir, target_dir) + self.assertEqual(coeff, source_norm / target_norm) + # the target is a genuine cubic diagram + self.assertEqual(amplitude.unrolled_diagram( + diagrams[target], {}, + diagram_generation.get_unrollable_quartic_vertices( + self.base_model)).get('vertices'), + diagrams[target].get('vertices')) + + # nothing is left behind: the contributions which are not linked are + # exactly the ones carried by a diagram without any quartic vertex + unrollable = diagram_generation.get_unrollable_quartic_vertices( + self.base_model) + cubic = [i for i, d in enumerate(diagrams) + if not any(v.get('id') in unrollable + for v in d.get('vertices'))] + unlinked = [piece for piece in directions if piece not in links] + self.assertEqual(sorted(piece[0] for piece in unlinked), sorted(cubic)) + + def test_unrollable_vertices_sm(self): + """The four gluon vertex is the only one factorising in the SM""" + + unrollable = diagram_generation.get_unrollable_quartic_vertices( + self.base_model) + self.assertEqual(len(unrollable), 1) + (cubic, pairings), = unrollable.values() + quartic, = unrollable.keys() + self.assertEqual([p.get_pdg_code() for p in + self.base_model.get_interaction(quartic).get('particles')], + [21, 21, 21, 21]) + self.assertEqual([p.get_pdg_code() for p in + self.base_model.get_interaction(cubic).get('particles')], + [21, 21, 21]) + # each colour structure splits the four legs into two pairs + self.assertEqual(pairings, [((0, 1), (2, 3)), + ((0, 2), (1, 3)), + ((0, 3), (1, 2))]) + + def test_unroll_gg_gg(self): + """g g > g g: the contact term merges into the s, t and u channel""" + + self.check_process([21, 21], [21, 21], 3) + + def test_unroll_gg_ggg(self): + """g g > g g g: 45 contributions collapse onto the 15 cubic diagrams""" + + self.check_process([21, 21], [21, 21, 21], 30) + + def test_unroll_gg_gggg(self): + """g g > g g g g: 510 contributions collapse onto 105 cubic diagrams""" + + self.check_process([21, 21], [21, 21, 21, 21], 405) + + def test_unroll_bbx_ggg(self): + """A quartic vertex sitting next to a colour triplet line""" + + self.check_process([5, -5], [21, 21, 21], 3) + + def test_unroll_gg_ttxg(self): + """The quartic vertex feeding an internal gluon of a t t~ pair""" + + self.check_process([21, 21], [6, -6, 21], 3) + + def test_links_match_helas_colour_indices(self): + """The links must be usable against HelasAmplitude. + + helas_objects colorizes the reconstructed base amplitude, whose + vertex order can differ from the generated diagrams, so the chains + only line up with HelasAmplitude.get('color_indices') when the + unrolling is run on get_base_amplitude().""" + + import madgraph.core.helas_objects as helas_objects + + amplitude = self.make_amplitude([21, 21], [21, 21, 21]) + matrix_element = helas_objects.HelasMatrixElement(amplitude) + base = matrix_element.get('base_amplitude') + + known = {} + for diagram in matrix_element.get('diagrams'): + for helas_amp in diagram.get('amplitudes'): + known[(diagram.get('number') - 1, + tuple(helas_amp.get('color_indices')))] = \ + helas_amp.get('number') + + links = base.unroll_quartic_vertices() + self.assertTrue(links) + for (diag, chain), (target, _) in links.items(): + target_chain = (0,) * len(base.get('diagrams')[target].get('vertices')) + self.assertIn((diag, chain), known) + self.assertIn((target, target_chain), known) + # every amplitude is either a merge target or folded into one + self.assertEqual(len(known) - len(links), + len(set(target for target, _ in links.values()))) + + def test_no_unrolling_without_quartic(self): + """Processes without a four gluon vertex give no link""" + + amplitude = self.make_amplitude([5, -5], [5, -5]) + self.assertEqual(amplitude.unroll_quartic_vertices(), {}) From 5c9cdb3019d8295b0710b29e7e321723c90b9f0a Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 00:06:01 +0200 Subject: [PATCH 02/39] record why the quartic currents cannot be summed as they stand get_quartic_wavefunction_merges looks for a quartic current and the cubic current it shares a colour factor with sitting at the same node, so that the sum can be done once on the current instead of on every amplitude it feeds. Both carry the same 1/P^2, so the sum itself is exact. It finds nothing, and that is the correct answer rather than a missing case. At six gluons there are 90 candidate pairs, but the two currents do not have matching consumers: quartic current 11 is used by amplitudes 7,9,36,38,60,62 whose images under the merge map are 1,31,55, while its cubic partner 9 is used by 1,5,31,34,55,58. Summing would hand the contribution to all six consumers of the partner while only three have an amplitude being dropped, so 5,34,58 would silently gain a term. The extra consumers are the diagrams whose own last vertex is quartic, which take their contribution from a different node. Attaching the contribution to the node itself, so that every consumer is entitled to it, needs the auxiliary current to be materialised rather than collapsed back into VVVVxP0_1. Co-Authored-By: Claude Opus 5 --- madgraph/core/helas_objects.py | 86 ++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/madgraph/core/helas_objects.py b/madgraph/core/helas_objects.py index 802e9cc816..b88038ac6a 100755 --- a/madgraph/core/helas_objects.py +++ b/madgraph/core/helas_objects.py @@ -4002,6 +4002,7 @@ def default_setup(self): # Cache for get_quartic_amplitude_merges(), needed both by the helas # calls and by the colour amplitudes. Runtime only, like the above. self.quartic_amplitude_merges = None + self.quartic_wavefunction_merges = None def filter(self, name, value): """Filter for valid diagram property values.""" @@ -6176,6 +6177,91 @@ def get_color_amplitudes(self): return [[entry for entry in col_amp if entry[1] not in merges] for col_amp in col_amps] + def get_quartic_wavefunction_merges(self): + """Pairs of currents which can be summed instead of their amplitudes. + + Where a quartic current and the cubic current it has to be summed with + sit at the same node, and the amplitudes using them differ by nothing + else, the sum can be done once on the current rather than on every + amplitude that current feeds. Both carry the same 1/P^2 through the + same propagator, so they simply add. + + Returns ({source number: (source, target, coeff)}, absorbed amplitude + numbers). The absorbed amplitudes are the ones the sum takes care of: + they must be left out of both the helas calls and the JAMPs. + """ + + if self.quartic_wavefunction_merges is None: + self.quartic_wavefunction_merges = \ + self.compute_quartic_wavefunction_merges() + return self.quartic_wavefunction_merges + + def compute_quartic_wavefunction_merges(self): + """Work out the current sums, see get_quartic_wavefunction_merges.""" + + merges = self.get_quartic_amplitude_merges() + if not merges: + return {}, set() + + model = self.get('processes')[0].get('model') + unrollable = diagram_generation.get_unrollable_quartic_vertices(model) + amplitudes = dict((amp.get('number'), amp) + for amp in self.get_all_amplitudes()) + + # every consumer of a wavefunction, so that a current is only summed + # away when nothing else is left needing it on its own + consumers = {} + for amp in self.get_all_amplitudes(): + for mother in amp.get('mothers'): + consumers.setdefault(mother.get('number'), []).append( + ('amplitude', amp.get('number'))) + for wf in self.get_all_wavefunctions(): + for mother in wf.get('mothers'): + consumers.setdefault(mother.get('number'), []).append( + ('wavefunction', wf.get('number'))) + + candidates = {} + absorbed = {} + for source, (target, coeff) in merges.items(): + mothers = amplitudes[source].get('mothers') + others = amplitudes[target].get('mothers') + if len(mothers) != len(others): + continue + numbers = [wf.get('number') for wf in others] + only_source = [wf for wf in mothers + if wf.get('number') not in numbers] + numbers = [wf.get('number') for wf in mothers] + only_target = [wf for wf in others + if wf.get('number') not in numbers] + if len(only_source) != 1 or len(only_target) != 1: + continue + quartic, cubic = only_source[0], only_target[0] + if quartic.get('interaction_id') not in unrollable or \ + cubic.get('interaction_id') in unrollable: + continue + key = quartic.get('number') + if key in candidates and candidates[key] != (quartic, cubic, coeff): + candidates[key] = None # not a single consistent sum + continue + candidates.setdefault(key, (quartic, cubic, coeff)) + absorbed.setdefault(key, set()).add(source) + + res = {} + taken = set() + for key, value in candidates.items(): + if value is None: + continue + # the sum only replaces this current if it accounts for every use + uses = consumers.get(key, []) + if any(kind == 'wavefunction' for kind, _ in uses): + continue + if set(number for _, number in uses) != absorbed[key]: + continue + res[key] = value + taken |= absorbed[key] + + return res, taken + def get_quartic_amplitude_merges(self): """Return {amplitude number: (target number, coefficient)} for the quartic gluon contributions which can be summed into another From 1c1722ae872e1854de21c6b84cb381e9cc7ae422 Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 00:53:11 +0200 Subject: [PATCH 03/39] drop the auxiliary line generation, keep the diagram set intact Splitting the quartic vertex into two cubic ones at generation time gave one diagram per colour structure: g g > 4g went from 220 diagrams to 510, and generation from 0.070s to 0.205s. The amplitude count was unchanged (510 either way) and so was |M|^2, but the diagram list is what the user sees, and what drives the MadEvent multichannel, so fragmenting it is not a trade worth making for the currents it shared. Reverted: get_auxiliary_model, collapse_auxiliary_diagrams, the Vertex 'color_key'/'aux_pair' pinning and everything honouring it in colorize, in the two colour expansion loops and in get_base_vertex. No auxiliary particle is left anywhere. Kept: unroll_quartic_vertices and the link map it builds, verified against the colour algebra for g g > N g, N=2..5, together with the amplitude sums which still emit 405 folds and still shrink the JAMP block from 1091 to 697 lines at six gluons. g g > 4g is back to 220 diagrams in 0.063s, |M|^2 unchanged. Co-Authored-By: Claude Opus 5 --- madgraph/core/base_objects.py | 24 +-- madgraph/core/color_amp.py | 6 - madgraph/core/diagram_generation.py | 239 +-------------------- madgraph/core/helas_objects.py | 139 +----------- tests/unit_tests/core/test_base_objects.py | 8 +- 5 files changed, 10 insertions(+), 406 deletions(-) diff --git a/madgraph/core/base_objects.py b/madgraph/core/base_objects.py index c9d4f2e641..18eff6a7bf 100755 --- a/madgraph/core/base_objects.py +++ b/madgraph/core/base_objects.py @@ -2979,7 +2979,7 @@ class Vertex(PhysicsObject): """Vertex: list of legs (ordered), id (Interaction) """ - sorted_keys = ['id', 'legs', 'color_key', 'aux_pair'] + sorted_keys = ['id', 'legs'] # This sets what are the ID's of the vertices that must be ignored for the # purpose of the multi-channeling. 0 and -1 are ID's of various technical @@ -3014,20 +3014,6 @@ def default_setup(self): # that it can be easily identified when constructing the DiagramChainLinks. self['id'] = 0 self['legs'] = LegList() - # Restrict the vertex to a single colour structure of its interaction. - # None (the default) means that all of them contribute, which is the - # normal situation. It is set when a quartic vertex has been recovered - # from the two cubic vertices it factorises into, since each such pair - # rebuilds one specific colour structure (see - # diagram_generation.Amplitude.collapse_auxiliary_diagrams). - self['color_key'] = None - # Numbers of the two legs which used to sit on the auxiliary line. - # The colour structure the vertex is restricted to is the one - # separating them, but which structure that is can only be settled - # once the mothers are in the order ALOHA receives them, so the pair - # is carried along and resolved in generate_helas_diagrams. - self['aux_pair'] = None - def filter(self, name, value): """Filter for valid vertex property values.""" @@ -3039,14 +3025,6 @@ def filter(self, name, value): if not isinstance(value, LegList): raise self.PhysicsObjectError("%s is not a valid LegList object" % str(value)) - if name == 'color_key': - if value is not None and not isinstance(value, int): - raise self.PhysicsObjectError("%s is not a valid colour key" % str(value)) - - if name == 'aux_pair': - if value is not None and not isinstance(value, tuple): - raise self.PhysicsObjectError("%s is not a valid auxiliary pair" % str(value)) - return True def get_sorted_keys(self): diff --git a/madgraph/core/color_amp.py b/madgraph/core/color_amp.py index 02aa2df09b..20850bde94 100755 --- a/madgraph/core/color_amp.py +++ b/madgraph/core/color_amp.py @@ -201,12 +201,6 @@ def add_vertex(self, vertex, diagram, model, # Ignore color string if it doesn't correspond to any coupling if i not in inter_indices: continue - - # A vertex rebuilt from the two cubic vertices it factorises into - # only carries the colour structure those two reproduce. - if vertex.get('color_key') is not None and \ - i != vertex.get('color_key'): - continue # Build the new element assert type(col_str) == color_algebra.ColorString diff --git a/madgraph/core/diagram_generation.py b/madgraph/core/diagram_generation.py index bbf031cc6d..20c59ce7a5 100755 --- a/madgraph/core/diagram_generation.py +++ b/madgraph/core/diagram_generation.py @@ -296,10 +296,6 @@ def vertex_id_from_vertex(vertex, last_vertex, model, ninitial): # return (vertex.get('id'),(),{'PDGs':vertex.get('PDGs')}) return ((vertex.get('id'),vertex.get('loop_tag')),(), {'PDGs':vertex.get('PDGs')}) - elif vertex.get('color_key') is not None: - # a vertex restricted to one colour structure is not the same - # vertex as the unrestricted one, nor as the other restrictions - return ((vertex.get('id'),(vertex.get('color_key'),)),(),{}) else: return ((vertex.get('id'),()),(),{}) @@ -511,26 +507,6 @@ def get_unrollable_quartic_vertices(model): return res -def pinned_color_key(helas_object): - """Colour structure a reconstructed vertex has to be restricted to. - - With merge_quartic_vertices the quartic vertices are recovered from the - two cubic ones they factorise into and therefore carry a single colour - structure. The diagram rebuilt from the helas objects has to say so, - otherwise colorize() expands all of them and the colour chains no longer - match the amplitudes that were actually generated.""" - - if not madgraph.merge_quartic_vertices: - return None - model = getattr(helas_object, 'model', None) - if model is None: - return None - if helas_object.get('interaction_id') in \ - get_unrollable_quartic_vertices(model): - return helas_object.get('color_key') - return None - - def _f_pair_split(col_str): """If col_str is f(..)*f(..) with a single shared summed index and the four remaining indices being 0,1,2,3, return the two pairs of external @@ -549,82 +525,6 @@ def _f_pair_split(col_str): return pairs -AUXILIARY_PDG_OFFSET = 9000000 - - -def get_auxiliary_model(model): - """Return a copy of model where every unrollable quartic vertex has been - replaced by two cubic vertices joined by an auxiliary line. - - Generating with this model gives one diagram per colour structure of the - quartic vertex, and -- this is the point -- the diagram carrying the - auxiliary line has exactly the same topology, and therefore exactly the - same decomposition, as the purely cubic diagram it has to be summed with. - The 'from_group' rule which makes that decomposition canonical only looks - at the topology, never at which particle sits on a line, so the two are - rooted identically and every current except the auxiliary line itself is - shared. The auxiliary lines are removed again by - Amplitude.collapse_auxiliary_diagrams before the diagrams are used. - - Returns (model, {auxiliary pdg: (quartic id, cubic id, pairings)}) or - (model, {}) if there is nothing to do. - - Note that copy.deepcopy must not be used on colour structures: ColorObject - derives from array.array and deepcopy silently turns it into a plain array. - """ - - unrollable = get_unrollable_quartic_vertices(model) - if not unrollable: - return model, {} - - particles = base_objects.ParticleList(model.get('particles')) - interactions = base_objects.InteractionList( - [inter for inter in model.get('interactions') - if inter.get('id') not in unrollable]) - next_id = max(inter.get('id') for inter in model.get('interactions')) + 1 - - auxiliaries = {} - for quartic_id, (cubic_id, pairings) in unrollable.items(): - quartic = model.get_interaction(quartic_id) - partner = quartic.get('particles')[0] - aux_pdg = AUXILIARY_PDG_OFFSET + partner.get_pdg_code() - auxiliary = base_objects.Particle({ - 'name': 'aux%d' % partner.get_pdg_code(), - 'antiname': 'aux%d' % partner.get_pdg_code(), - 'spin': partner.get('spin'), 'color': partner.get('color'), - 'charge': 0., 'mass': 'ZERO', 'width': 'ZERO', - 'pdg_code': aux_pdg, 'line': partner.get('line'), - 'is_part': True, 'self_antipart': True}) - particles.append(auxiliary) - - # the quartic coupling order is shared between the two cubic vertices - orders = dict((order, value // 2) - for order, value in quartic.get('orders').items()) - interactions.append(base_objects.Interaction({ - 'id': next_id, - 'particles': base_objects.ParticleList( - [partner, partner, auxiliary]), - 'color': [color_algebra.ColorString( - [color_algebra.f(0, 1, 2)])], - 'lorentz': model.get_interaction(cubic_id).get('lorentz'), - 'couplings': dict(model.get_interaction(cubic_id).get('couplings')), - 'orders': orders})) - auxiliaries[aux_pdg] = (quartic_id, next_id, pairings) - next_id += 1 - - aux_model = base_objects.Model() - aux_model.set('particles', particles) - aux_model.set('interactions', interactions) - for key in ('name', 'order_hierarchy', 'conserved_charge', - 'coupling_orders', 'expansion_order'): - try: - aux_model.set(key, model.get(key)) - except Exception: - pass - - return aux_model, auxiliaries - - def colour_index_order(vertex, is_last, model): """Return the vertex legs in the order in which color_amp.ColorBasis maps them onto the colour indices of the interaction. @@ -979,30 +879,6 @@ def generate_diagrams(self, returndiag=False, diagram_filter=False): assert model.get('interactions'), \ "interactions are missing in model" - # Generate with every unrollable quartic vertex split into the two - # cubic vertices it factorises into, then put them back together. This - # gives one diagram per colour structure of the quartic vertex, each - # sharing its topology -- and hence its currents -- with the purely - # cubic diagram it has to be summed with. The auxiliary model has no - # unrollable vertex left, so the recursion below stops immediately. - if madgraph.merge_quartic_vertices and \ - not process.get('is_decay_chain'): - aux_model, auxiliaries = get_auxiliary_model(model) - if auxiliaries: - aux_process = copy.copy(process) - aux_process.set('model', aux_model) - aux_amplitude = Amplitude() - aux_amplitude.set('process', aux_process) - success = aux_amplitude.generate_diagrams( - diagram_filter=diagram_filter) - res = self.collapse_auxiliary_diagrams( - aux_amplitude.get('diagrams'), auxiliaries) - self.trim_diagrams(diaglist=res) - if returndiag: - return success, res - self['diagrams'] = res - return success - res = base_objects.DiagramList() # First check that the number of fermions is even if len([leg for leg in legs if model.get('particle_dict')[\ @@ -1422,17 +1298,11 @@ def unroll_quartic_vertices(self, diaglist=None): if not positions: continue # only the colour structures which carry a coupling contribute, - # matching what color_amp.ColorBasis.colorize keeps, and a vertex - # pinned to one structure contributes only that one - allowed = [] - for position in positions: - vertex = diag.get('vertices')[position] - if vertex.get('color_key') is not None: - allowed.append([vertex.get('color_key')]) - else: - allowed.append(sorted(misc.make_unique( - [key[0] for key in model.get_interaction( - vertex.get('id')).get('couplings')]))) + # matching what color_amp.ColorBasis.colorize keeps + allowed = [sorted(misc.make_unique( + [key[0] for key in model.get_interaction( + diag.get('vertices')[p].get('id')).get('couplings')])) + for p in positions] for keys in itertools.product(*allowed): choice = dict(zip(positions, keys)) unrolled = self.unrolled_diagram(diag, choice, unrollable) @@ -1458,105 +1328,6 @@ def unroll_quartic_vertices(self, diaglist=None): return res - def collapse_auxiliary_diagrams(self, diaglist, auxiliaries): - """Turn every auxiliary line back into the quartic vertex it stands for. - - The two cubic vertices sharing an auxiliary line rebuild one specific - colour structure of the quartic vertex, so the recovered vertex is - pinned to that structure through its 'color_key'. The legs are ordered - so that the pair which used to sit on the auxiliary line lands on the - colour indices that structure separates. - """ - - if not auxiliaries: - return diaglist - - res = diaglist.__class__() - for diagram in diaglist: - vertices = diagram.get('vertices') - last = len(vertices) - 1 - # an auxiliary line is produced by the vertex whose outgoing leg - # carries it, and consumed by the one having it as an incoming leg - produced = {} - for i, vertex in enumerate(vertices): - if i == last: - continue - pdg = vertex.get('legs')[-1].get('id') - if pdg in auxiliaries: - produced[vertex.get('legs')[-1].get('number')] = (i, pdg) - - if not produced: - res.append(diagram) - continue - - collapsed = {} - for i, vertex in enumerate(vertices): - incoming = vertex.get('legs') if i == last \ - else vertex.get('legs')[:-1] - for position, leg in enumerate(incoming): - if leg.get('id') not in auxiliaries: - continue - collapsed[i] = (produced[leg.get('number')][0], position, - auxiliaries[leg.get('id')]) - - new_vertices = base_objects.VertexList() - for i, vertex in enumerate(vertices): - if i in [source for source, _, _ in collapsed.values()]: - continue # the producer disappears into the consumer - if i not in collapsed: - new_vertices.append(vertex) - continue - source, position, (quartic_id, _, pairings) = collapsed[i] - pair = list(vertices[source].get('legs')[:-1]) - rest = [leg for j, leg in enumerate( - vertex.get('legs') if i == last - else vertex.get('legs')[:-1]) if j != position] - new_vertices.append(self.collapsed_vertex( - pair, rest, None if i == last else vertex.get('legs')[-1], - quartic_id, pairings)) - res.append(base_objects.Diagram({'vertices': new_vertices})) - - return res - - def collapsed_vertex(self, pair, rest, outgoing, quartic_id, pairings): - """Build the quartic vertex standing for an auxiliary line separating - pair from rest, pinned to the colour structure which does that split.""" - - # The incoming legs are kept in a canonical order rather than in an - # order chosen to suit the pair: the three vertices recovered from the - # three pairings of the same quartic vertex have to differ by their - # colour structure only. Reordering them instead would make them the - # same vertex once the helas mothers are sorted, and one structure - # would be counted three times. - incoming = sorted(rest + pair, key=lambda leg: leg.get('number')) - legs = base_objects.LegList(incoming) - if outgoing is not None: - legs.append(outgoing) - vertex = base_objects.Vertex({'legs': legs, 'id': quartic_id}) - - # An unrollable quartic vertex has four legs of the same particle, so - # ordering on the interaction particles leaves them alone and the - # colour index order is just the outgoing leg moved to the front. - offset = 0 if outgoing is None else 1 - numbers = [leg.get('number') for leg in incoming] - positions = frozenset(offset + numbers.index(leg.get('number')) - for leg in pair) - for key, pairing in enumerate(pairings): - if frozenset(pairing[0]) == positions or \ - frozenset(pairing[1]) == positions: - # This key labels the pairing in the leg order used here, which - # is enough to keep the three recovered vertices distinct. The - # key actually used is settled against the helas mother order - # by HelasMatrixElement.resolve_auxiliary_color_key. - vertex.set('color_key', key) - vertex.set('aux_pair', - tuple(leg.get('number') for leg in pair)) - return vertex - - raise MadGraph5Error( - 'No colour structure of interaction %d separates the auxiliary ' - 'pair' % quartic_id) - def unrolled_diagram(self, diagram, choice, unrollable): """Return a copy of diagram where the quartic vertices listed in choice (position -> colour structure index) have been replaced by the diff --git a/madgraph/core/helas_objects.py b/madgraph/core/helas_objects.py index b88038ac6a..fc7562fb61 100755 --- a/madgraph/core/helas_objects.py +++ b/madgraph/core/helas_objects.py @@ -2054,8 +2054,7 @@ def get_base_vertex(self, wf_dict, vx_list = [], optimization = 1): vertex = base_objects.Vertex({ 'id': self.get('interaction_id'), - 'legs': legs, - 'color_key': diagram_generation.pinned_color_key(self)}) + 'legs': legs}) return vertex @@ -3412,8 +3411,7 @@ def get_base_vertex(self, wf_dict, vx_list = [], optimization = 1): return base_objects.Vertex({ 'id': self.get('interaction_id'), - 'legs': legs, - 'color_key': diagram_generation.pinned_color_key(self)}) + 'legs': legs}) def get_s_and_t_channels(self, ninitial, model, new_pdg, reverse_t_ch = False): """Returns two lists of vertices corresponding to the s- and @@ -4002,7 +4000,6 @@ def default_setup(self): # Cache for get_quartic_amplitude_merges(), needed both by the helas # calls and by the colour amplitudes. Runtime only, like the above. self.quartic_amplitude_merges = None - self.quartic_wavefunction_merges = None def filter(self, name, value): """Filter for valid diagram property values.""" @@ -4233,15 +4230,6 @@ def generate_helas_diagrams(self, amplitude, optimization=1,decay_ids=[]): done_color = {} # store link to color for coupl_key in sorted(inter.get('couplings').keys()): color = coupl_key[0] - # a vertex rebuilt from two cubic vertices only carries - # the colour structure those two reproduce - if vertex.get('color_key') is not None: - probe = HelasWavefunction(last_leg, - vertex.get('id'), model) - probe.set('mothers', mothers) - if color != self.resolve_auxiliary_color_key( - probe, vertex, model): - continue if color in done_color: wf = done_color[color] wf.get('coupling').append(inter.get('couplings')[coupl_key]) @@ -4343,14 +4331,6 @@ def generate_helas_diagrams(self, amplitude, optimization=1,decay_ids=[]): done_color = {} for i, coupl_key in enumerate(keys): color = coupl_key[0] - # a vertex rebuilt from two cubic vertices only carries - # the colour structure those two reproduce - if inter and lastvx.get('color_key') is not None: - probe = HelasAmplitude(lastvx, model) - probe.set('mothers', mothers) - if color != self.resolve_auxiliary_color_key( - probe, lastvx, model): - continue if inter and color in list(done_color.keys()): amp = done_color[color] amp.get('coupling').append(inter.get('couplings')[coupl_key]) @@ -6131,36 +6111,6 @@ def generate_color_amplitudes(self, color_basis, diagrams): return col_amp_list - @staticmethod - def resolve_auxiliary_color_key(candidate, vertex, model): - """Colour structure a recovered quartic vertex is restricted to. - - The vertex was rebuilt from two cubic vertices sharing an auxiliary - line, so it only carries the colour structure separating the pair that - used to sit on that line. Which structure that is depends on the order - in which ALOHA receives the legs, so it can only be settled here, - against sorted_mothers, and not on the generated diagram.""" - - pair = vertex.get('aux_pair') - pairings = diagram_generation.get_unrollable_quartic_vertices( - model).get(vertex.get('id'), (None, None))[1] - if pair is None or pairings is None: - return vertex.get('color_key') - - mothers = HelasMatrixElement.sorted_mothers(candidate) - if isinstance(candidate, HelasWavefunction): - outgoing = candidate.find_outgoing_number() - 1 - slots = [i for i in range(len(mothers) + 1) if i != outgoing] - else: - slots = list(range(len(mothers))) - wanted = frozenset(slots[i] for i, mother in enumerate(mothers) - if mother.get('number_external') in pair) - for key, pairing in enumerate(pairings): - if frozenset(pairing[0]) == wanted or \ - frozenset(pairing[1]) == wanted: - return key - return vertex.get('color_key') - def get_color_amplitudes(self): """Return a list of (coefficient, amplitude number) lists, corresponding to the JAMPs for this matrix element. The @@ -6177,91 +6127,6 @@ def get_color_amplitudes(self): return [[entry for entry in col_amp if entry[1] not in merges] for col_amp in col_amps] - def get_quartic_wavefunction_merges(self): - """Pairs of currents which can be summed instead of their amplitudes. - - Where a quartic current and the cubic current it has to be summed with - sit at the same node, and the amplitudes using them differ by nothing - else, the sum can be done once on the current rather than on every - amplitude that current feeds. Both carry the same 1/P^2 through the - same propagator, so they simply add. - - Returns ({source number: (source, target, coeff)}, absorbed amplitude - numbers). The absorbed amplitudes are the ones the sum takes care of: - they must be left out of both the helas calls and the JAMPs. - """ - - if self.quartic_wavefunction_merges is None: - self.quartic_wavefunction_merges = \ - self.compute_quartic_wavefunction_merges() - return self.quartic_wavefunction_merges - - def compute_quartic_wavefunction_merges(self): - """Work out the current sums, see get_quartic_wavefunction_merges.""" - - merges = self.get_quartic_amplitude_merges() - if not merges: - return {}, set() - - model = self.get('processes')[0].get('model') - unrollable = diagram_generation.get_unrollable_quartic_vertices(model) - amplitudes = dict((amp.get('number'), amp) - for amp in self.get_all_amplitudes()) - - # every consumer of a wavefunction, so that a current is only summed - # away when nothing else is left needing it on its own - consumers = {} - for amp in self.get_all_amplitudes(): - for mother in amp.get('mothers'): - consumers.setdefault(mother.get('number'), []).append( - ('amplitude', amp.get('number'))) - for wf in self.get_all_wavefunctions(): - for mother in wf.get('mothers'): - consumers.setdefault(mother.get('number'), []).append( - ('wavefunction', wf.get('number'))) - - candidates = {} - absorbed = {} - for source, (target, coeff) in merges.items(): - mothers = amplitudes[source].get('mothers') - others = amplitudes[target].get('mothers') - if len(mothers) != len(others): - continue - numbers = [wf.get('number') for wf in others] - only_source = [wf for wf in mothers - if wf.get('number') not in numbers] - numbers = [wf.get('number') for wf in mothers] - only_target = [wf for wf in others - if wf.get('number') not in numbers] - if len(only_source) != 1 or len(only_target) != 1: - continue - quartic, cubic = only_source[0], only_target[0] - if quartic.get('interaction_id') not in unrollable or \ - cubic.get('interaction_id') in unrollable: - continue - key = quartic.get('number') - if key in candidates and candidates[key] != (quartic, cubic, coeff): - candidates[key] = None # not a single consistent sum - continue - candidates.setdefault(key, (quartic, cubic, coeff)) - absorbed.setdefault(key, set()).add(source) - - res = {} - taken = set() - for key, value in candidates.items(): - if value is None: - continue - # the sum only replaces this current if it accounts for every use - uses = consumers.get(key, []) - if any(kind == 'wavefunction' for kind, _ in uses): - continue - if set(number for _, number in uses) != absorbed[key]: - continue - res[key] = value - taken |= absorbed[key] - - return res, taken - def get_quartic_amplitude_merges(self): """Return {amplitude number: (target number, coefficient)} for the quartic gluon contributions which can be summed into another diff --git a/tests/unit_tests/core/test_base_objects.py b/tests/unit_tests/core/test_base_objects.py index 0dfba047c8..65d99dce7c 100755 --- a/tests/unit_tests/core/test_base_objects.py +++ b/tests/unit_tests/core/test_base_objects.py @@ -1473,9 +1473,7 @@ class VertexTest(unittest.TestCase): def setUp(self): self.mydict = {'id':3, - 'legs':self.myleglist, - 'color_key':None, - 'aux_pair':None} + 'legs':self.myleglist} self.myvertex = base_objects.Vertex(self.mydict) @@ -1549,9 +1547,7 @@ def test_representation(self): goal = "{\n" goal = goal + " \'id\': 3,\n" - goal = goal + " \'legs\': %s,\n" % repr(self.myleglist) - goal = goal + " \'color_key\': None,\n" - goal = goal + " \'aux_pair\': None\n}" + goal = goal + " \'legs\': %s\n}" % repr(self.myleglist) self.assertEqual(goal, str(self.myvertex)) From 98d288f41b76dafe0d0065dde1bf03aee3cc7758 Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 00:59:05 +0200 Subject: [PATCH 04/39] add reroot_diagram, turning a diagram around its final vertex A diagram is a tree, and which of its vertices is written last decides which internal lines become currents: everything on the far side of the final vertex is built up as a wavefunction, while the final vertex only produces an amplitude. Re-rooting therefore changes which currents exist without changing the diagram, which is what will let a quartic current find the cubic current carrying the same colour factor. The vertices are first split into the external legs they hold and the internal lines they share, since a leg number alone does not identify a line -- a vertex reuses the smallest incoming number for the leg it produces. The tree is then walked outwards from the new root, and the line pointing back at it becomes each vertex's outgoing leg, flipped to the antiparticle where the re-rooting reverses it. Checked against UnrollDiagramTag for g g > N g, N=2..4: all 7, 65 and 755 possible rerootings give back the same diagram, none altered, none refused. They are not no-ops either -- at six gluons a diagram reaches 2, 3 or 4 distinct sets of currents depending on where it is rooted. Nothing calls this yet. Co-Authored-By: Claude Opus 5 --- madgraph/core/diagram_generation.py | 92 +++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/madgraph/core/diagram_generation.py b/madgraph/core/diagram_generation.py index 20c59ce7a5..e31d12e6c4 100755 --- a/madgraph/core/diagram_generation.py +++ b/madgraph/core/diagram_generation.py @@ -609,6 +609,98 @@ def split_quartic_vertex(vertex, is_last, pairing, cubic_id, model): _SUMMED = 'summed' +def reroot_diagram(diagram, root, model): + """Return the same diagram decomposed around another final vertex. + + A diagram is a tree, and which of its vertices is written last decides + which internal lines become currents: everything on the far side of the + final vertex is built up as a wavefunction, while the final vertex only + produces an amplitude. Re-rooting therefore changes which currents exist + without changing the diagram -- same vertices, same lines, same physics -- + which is what lets a quartic current find the cubic current it has to be + summed with. + + root is the index of the vertex to end on. Returns None if the diagram + does not decompose into a tree, which should not happen. + """ + + vertices = diagram.get('vertices') + last = len(vertices) - 1 + if root == last: + return diagram + + # Split every vertex into the external legs it holds and the internal + # lines it shares with another vertex. A line is recognised by its number + # being live, since a vertex reuses the smallest incoming number for the + # leg it produces. + live = {} + externals = [[] for _ in vertices] + lines = [] + for i, vertex in enumerate(vertices): + incoming = vertex.get('legs') if i == last else vertex.get('legs')[:-1] + for leg in incoming: + producer = live.pop(leg.get('number'), None) + if producer is None: + externals[i].append(leg) + else: + lines.append((producer, i, + vertices[producer].get('legs')[-1])) + if i != last: + live[vertex.get('legs')[-1].get('number')] = i + if live: + return None + + neighbours = {} + line_of = {} + for producer, consumer, leg in lines: + neighbours.setdefault(producer, []).append(consumer) + neighbours.setdefault(consumer, []).append(producer) + line_of[(producer, consumer)] = (leg, True) + line_of[(consumer, producer)] = (leg, False) + + # Walk out from the new root so that every vertex is emitted after the + # ones now feeding it. + order = [] + parent = {root: None} + def visit(node): + for other in neighbours.get(node, []): + if other == parent[node]: + continue + parent[other] = node + visit(other) + order.append(node) + visit(root) + if len(order) != len(vertices): + return None + + produced = {} + res = base_objects.VertexList() + for node in order: + incoming = list(externals[node]) + for other in neighbours.get(node, []): + if other != parent[node]: + incoming.append(produced[other]) + legs = base_objects.LegList(incoming) + if node != root: + leg, forwards = line_of[(node, parent[node])] + part = model.get('particle_dict')[leg.get('id')] + outgoing = base_objects.Leg({ + # the line keeps its particle if it already pointed this way, + # and is flipped when the re-rooting reverses it + 'id': leg.get('id') if forwards or part.get('self_antipart') + else -leg.get('id'), + 'number': min(l.get('number') for l in incoming), + 'state': len([l for l in incoming + if not l.get('state')]) != 1, + 'from_group': True}) + produced[node] = outgoing + legs.append(outgoing) + res.append(base_objects.Vertex({'legs': legs, + 'id': vertices[node].get('id')})) + + return base_objects.Diagram({'vertices': res}) + + def diagram_colour_signature(diagram, model, color_chain, unrollable): """Canonical signature of the colour string of one colour structure choice. From 3b3ed9e85a744dbb38bdaf28afaeb2e247b271af Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 01:21:04 +0200 Subject: [PATCH 05/39] add the plan for the pure gluon amplitude optimisation Written so the work can be picked up in a clean session: what is established by measurement, what is already committed, the five remaining steps, and the seven pitfalls that cost time getting here. The key result it rests on is the seed rule -- forbid two 3-gluon vertices from sharing a line. Unrolling a quartic always produces two adjacent cubic vertices, so a diagram is reachable iff it has an adjacent cubic pair to contract back, which makes that seed necessary and sufficient. It reconstructs the full diagram set exactly at 4, 5, 6 and 7 gluons from 25%, 40%, 25% and 15.5% of the diagrams. Co-Authored-By: Claude Opus 5 --- docs/gluon-quartic-plan.md | 139 +++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 docs/gluon-quartic-plan.md diff --git a/docs/gluon-quartic-plan.md b/docs/gluon-quartic-plan.md new file mode 100644 index 0000000000..4f405e7b94 --- /dev/null +++ b/docs/gluon-quartic-plan.md @@ -0,0 +1,139 @@ +# Pure-gluon amplitude optimisation — plan + +Branch `claude/gluon-amplitude-optimization-8706f5`. Everything is behind +`MG_MERGE_QUARTIC` (off by default), so nothing changes until it is set. + +## Goal + +Each colour structure of the 4-gluon vertex carries the *same colour factor* +as the diagram obtained by splitting that vertex into two cubic ones. So the +quartic current and the cubic current carrying that colour factor can be +summed into one current, and the whole subtree below it emitted once instead +of twice — a Berends-Giele style recursion, without colour ordering. + +``` +TMP = VVVVk_1(W_a,W_b,W_c) + VVV1P0_1(VVV1P0_1(W_a,W_b), W_c) +``` +Both carry the same `1/P^2` through the same propagator, so this is a plain +sum. Same for amplitudes. + +## Established facts (measured, not assumed) + +**1. The colour identity holds exactly.** Grouping every amplitude piece by +its colour vector over the ColorBasis: + +| process | amplitude pieces | colour groups | cubic diagrams per group | +|---|---|---|---| +| `g g > g g` | 6 | 3 | exactly 1 | +| `g g > g g g` | 45 | 15 | exactly 1 | +| `g g > g g g g` | 510 | 105 | exactly 1 | + +Every quartic piece is colour-proportional (±1) to exactly one cubic diagram. +Merged count == pure-cubic diagram count == `(2n-5)!!`. `g g > 4g` also +verified in generated Fortran: folding 405 of 510 amplitudes and zeroing the +sources leaves `|M|^2` bit-identical. + +**2. The seed rule — forbid two 3-gluon vertices from sharing a line.** + +| process | full | seed | seed % | reconstructed by unrolling | missing | +|---|---|---|---|---|---| +| `g g > g g` | 4 | 1 | 25% | 4 | 0 | +| `g g > g g g` | 25 | 10 | 40% | 25 | 0 | +| `g g > g g g g` | 220 | 55 | 25% | 220 | 0 | +| `g g > g g g g g` | 2485 | 385 | 15.5% | 2485 | 0 | + +This is forced, not tuned. Unrolling a quartic vertex always yields two +**adjacent** cubic vertices (joined by the line that replaced the vertex), so +a diagram is reachable iff it has an adjacent cubic pair to contract back. +The diagrams with no such pair are exactly the ones that must be in the seed, +and every diagram either has such a pair or is in the seed — necessary and +sufficient, hence exact coverage. + +Note "no 3-gluon vertices **at all**" is the over-restrictive special case: it +loses the diagrams whose cubic vertices are non-adjacent (60 of 220 at six +gluons). + +**3. Reconstruction gives matched rootings for free.** A reconstructed diagram +and its quartic partner come from the *same* seed diagram, so they share a +decomposition and every current except the one being summed. This is the +property the whole optimisation needs. + +## Already committed + +| commit | what | +|---|---| +| `fcd8218b6` | link map (`unroll_quartic_vertices`, verified vs colour algebra, N=2..5) + amplitude sums | +| `5c9cdb301` | why the current sums fail on the un-rewired DAG | +| `1c1722ae8` | revert of the auxiliary-particle generation | +| `98d288f41` | `reroot_diagram`, validated 755/755 — probably NOT needed under the seed rule | + +Useful pieces to keep: `get_unrollable_quartic_vertices`, +`unroll_quartic_vertices`, `diagram_colour_signature`, `UnrollDiagramTag`, +`split_quartic_vertex`, `unrolled_diagram`, `get_quartic_amplitude_merges`, +`get_amplitude_merge_lines`. + +## Plan + +**Step 1 — enforce the seed rule in generation.** Reject any combination that +puts two 3-gluon vertices on the same line, inside `reduce_leglist` / +`merge_comb_legs`. Verify the generated seed is exactly the filtered set +measured above (1 / 10 / 55 / 385). *Do not assume it is* — `from_group` +decides which combinations are offered and that interaction has been +mis-predicted before. + +**Step 2 — reconstruct the full set by unrolling the seed.** For every seed +diagram, every subset of its quartic vertices, every colour structure. Dedup +with `UnrollDiagramTag`. Gate: diagram count exactly equal to baseline +(4/25/220/2485) and `|M|^2` unchanged. A double count would hide here. + +**Step 3 — record the link during reconstruction.** Free: the quartic diagram +and its cubic partner are the same seed diagram unrolled differently. Replaces +the colour-vector matching, which stays as the independent cross-check. + +**Step 4 — the current sum.** Where a quartic current and its cubic partner +sit at the same node, emit `TMP = W1 + W4` and the subtree once. Prerequisite, +checked explicitly: their consumers must correspond 1:1 (see pitfall 6). + +**Step 5 — validate and time.** `|M|^2` for `g g > N g`, N=2..5 against +baseline; per-call timing with a driver looping `SMATRIX` (the shipped +`check_sa` measures startup, not the ME). + +## Pitfalls — all of these cost real time in the previous session + +1. **Do not fragment the diagram list.** Generating one diagram per colour + structure (220 -> 510) works numerically but changes a user-visible number + and the MadEvent multichannel. It was reverted for that reason. +2. **`copy.deepcopy` on a `Model` silently breaks colour.** `ColorObject` + derives from `array.array` and deepcopy degrades it to a plain `array`, so + the structures stop being recognisable. Use `create_copy`. +3. **Two colour-chain conventions exist.** `helas_objects` colorizes the + *reconstructed* amplitude (`get_base_amplitude`), whose vertex order can + differ from the generated diagrams. They agree up to six gluons and diverge + at seven. Anything mapping chains to amplitudes must use the reconstructed + one. +4. **Pinning a single colour structure needs colour and Lorentz in the same + frame.** The sum over the three structures is permutation invariant but the + individual terms are not, so the structure must be chosen against + `sorted_mothers` (what ALOHA receives), not the vertex leg order. +5. **The `get_color_amplitudes` filter and the writer emitting the folds must + land together.** Filtering without emitting silently drops the quartic + contributions from the JAMPs — this produced a wrong `|M|^2` that survived + three rounds of debugging because the helas calls looked byte-identical to + baseline. When a number is wrong, diff the JAMP block first. +6. **A current sum is only legitimate if the consumers correspond 1:1.** + Summing into a shared current hands the contribution to *every* consumer. + Measured counter-example on the fragmented structure: quartic current 11 + had consumers {7,9,36,38,60,62} mapping to {1,31,55}, while its partner had + {1,5,31,34,55,58} — three consumers would have gained a term they must not + have. +7. **The amplitude sums buy nothing at runtime.** The JAMP CSE already finds + those pairs (`TMP_JAMP(2) = AMP(1) + AMP(4)`). They do shrink the JAMP block + (1091 -> 697 lines at six gluons), which helps the optimiser and compile + time. Expect the speedup to come from the currents, not from these. + +## Measuring + +Generation: `MG_MERGE_QUARTIC=1 ./bin/mg5_aMC` then `generate g g > g g g g`. +Compare `matrix.f` against a run without the variable. Tests: +`./tests/test_manager.py -p U test_diagram_generation test_color_amp +test_helas_objects test_base_objects` (199, must stay green with the flag off). From 25fc6d1cc68e6dcfa55a7467c006a107487e6e5d Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 01:37:01 +0200 Subject: [PATCH 06/39] enforce the seed rule inside diagram generation Unrolling a quartic vertex always yields two cubic vertices joined by the line which replaced it, so a diagram can be put back that way exactly when two of its cubic vertices already share a line. The diagrams which have no such pair are the ones generation has to produce, and every other one is reachable from them -- necessary and sufficient, hence exact coverage. reduce_leglist now drops any combination which puts two of those cubic vertices on the same line, tracking the lines they produce by leg number. The closing vertex needs both cases: a real n->0 interaction takes its legs as lines coming in, while the identity vertex states that its two legs are the two ends of one line, which is how a 2->2 reduction ends -- missing that one left g g > g g with its full four diagrams. Measured against the full generation filtered by an independently written adjacency detector, comparing the diagrams themselves and not just counts: g g > g g 4 -> 1 g g > g g g 25 -> 10 g g > g g g g 220 -> 55 g g > 5 g 2485 -> 385 g g > 6 g 34300 -> 4165 g g > t t~ g g 123 -> 84 Behind MG_MERGE_QUARTIC, off by default. Co-Authored-By: Claude Opus 5 --- madgraph/core/diagram_generation.py | 88 +++++++++++++- .../core/test_diagram_generation.py | 107 ++++++++++++++++++ 2 files changed, 193 insertions(+), 2 deletions(-) diff --git a/madgraph/core/diagram_generation.py b/madgraph/core/diagram_generation.py index e31d12e6c4..9dd7ba0916 100755 --- a/madgraph/core/diagram_generation.py +++ b/madgraph/core/diagram_generation.py @@ -525,6 +525,14 @@ def _f_pair_split(col_str): return pairs +def get_unrollable_cubic_ids(model): + """Interaction ids of the cubic vertices a factorisable quartic vertex + unrolls into -- the three gluon vertex for the four gluon one.""" + + return frozenset(cubic_id for cubic_id, pairings in + get_unrollable_quartic_vertices(model).values()) + + def colour_index_order(vertex, is_last, model): """Return the vertex legs in the order in which color_amp.ColorBasis maps them onto the colour indices of the interaction. @@ -825,6 +833,11 @@ class Amplitude(base_objects.PhysicsObject): generate the diagrams for the amplitude """ + # Interaction ids of the cubic vertices which the seed rule forbids to + # share a line, see generate_diagrams. Empty -- so the rule is inactive -- + # unless madgraph.merge_quartic_vertices is set. + seed_forbidden_cubic_ids = frozenset() + def default_setup(self): """Default values for all properties""" @@ -1056,6 +1069,16 @@ def generate_diagrams(self, returndiag=False, diagram_filter=False): max_multi_to1 = max([len(key) for key in \ model.get('ref_dict_to1').keys()]) + # Seed rule: when the quartic vertices are to be put back afterwards + # by unrolling (see unroll_quartic_vertices), generate only the + # diagrams unrolling cannot produce. Unrolling a quartic vertex always + # yields two cubic vertices sharing the line which replaced it, so a + # diagram can be reconstructed exactly when two of its cubic vertices + # share a line -- and the seed is what is left over. + self.seed_forbidden_cubic_ids = frozenset() + if madgraph.merge_quartic_vertices and not self.has_loop_process(): + self.seed_forbidden_cubic_ids = get_unrollable_cubic_ids(model) + # Reduce the leg list and return the corresponding # list of vertices @@ -1482,9 +1505,14 @@ def copy_leglist(self, legs): [ copy.copy(leg) for leg in legs ]) def reduce_leglist(self, curr_leglist, max_multi_to1, ref_dict_to0, - is_decay_proc = False, coupling_orders = None): + is_decay_proc = False, coupling_orders = None, + cubic_legs = frozenset()): """Recursive function to reduce N LegList to N-1 For algorithm, see doc for generate_diagrams. + + cubic_legs holds the numbers of the legs of curr_leglist which were + produced by a vertex the seed rule keeps apart, and is only ever + non-empty when that rule is active. """ # Result variable which is a list of lists of vertices @@ -1517,6 +1545,8 @@ def reduce_leglist(self, curr_leglist, max_multi_to1, ref_dict_to0, vertex_id in vertex_ids] # Check for coupling orders. If orders < 0, skip vertex for final_vertex in final_vertices: + if self.joins_two_cubics(final_vertex, cubic_legs): + continue if self.reduce_orders(coupling_orders, model, [final_vertex.get('id')]) != False: res.append([final_vertex]) @@ -1554,13 +1584,24 @@ def reduce_leglist(self, curr_leglist, max_multi_to1, ref_dict_to0, # Some coupling order < 0 continue + # Seed rule: drop the combinations putting two of the cubic + # vertices to be kept apart on the same line + if any(self.shares_line_with_cubic(vertex.get('id'), + vertex.get('legs')[:-1], + cubic_legs) + for vertex in leg_vertex_tuple[1]): + continue + # This is where recursion happens # First, reduce again the leg part reduced_diagram = self.reduce_leglist(leg_vertex_tuple[0], max_multi_to1, ref_dict_to0, is_decay_proc, - new_coupling_orders) + new_coupling_orders, + self.mark_cubic_legs(\ + cubic_legs, + leg_vertex_tuple[1])) # If there is a reduced diagram if reduced_diagram: vertex_list_list = [list(leg_vertex_tuple[1])] @@ -1570,6 +1611,49 @@ def reduce_leglist(self, curr_leglist, max_multi_to1, ref_dict_to0, return res + def shares_line_with_cubic(self, vertex_id, incoming, cubic_legs): + """True when vertex_id is one of the cubic vertices the seed rule + keeps apart and one of the lines coming in was produced by another + one of them.""" + + if not self.seed_forbidden_cubic_ids or \ + vertex_id not in self.seed_forbidden_cubic_ids: + return False + return any(leg.get('number') in cubic_legs for leg in incoming) + + def joins_two_cubics(self, vertex, cubic_legs): + """True when the vertex closing the diagram puts two of the cubic + vertices the seed rule keeps apart on the same line. + + The closing vertex is either a real n->0 interaction, whose incoming + lines are simply the legs left over, or the identity vertex, which + states that its two legs are the two ends of one and the same line -- + and that line joins the two vertices which produced them.""" + + if not self.seed_forbidden_cubic_ids: + return False + legs = vertex.get('legs') + if vertex.get('id'): + return self.shares_line_with_cubic(vertex.get('id'), legs, + cubic_legs) + return all(leg.get('number') in cubic_legs for leg in legs) + + def mark_cubic_legs(self, cubic_legs, vertices): + """Update the set of leg numbers standing for a line produced by one + of the cubic vertices the seed rule keeps apart. + + A number is dropped as soon as the line is consumed, since a vertex + reuses the smallest number coming in for the leg it produces.""" + + if not self.seed_forbidden_cubic_ids: + return cubic_legs + consumed = frozenset(leg.get('number') for vertex in vertices + for leg in vertex.get('legs')[:-1]) + produced = frozenset(vertex.get('legs')[-1].get('number') + for vertex in vertices if vertex.get('id') in \ + self.seed_forbidden_cubic_ids) + return (cubic_legs - consumed) | produced + def reduce_orders(self, coupling_orders, model, vertex_id_list): """Return False if the coupling orders for any coupling is < 0, otherwise return the new coupling orders with the vertex diff --git a/tests/unit_tests/core/test_diagram_generation.py b/tests/unit_tests/core/test_diagram_generation.py index cdb7bc2908..750fc241f0 100755 --- a/tests/unit_tests/core/test_diagram_generation.py +++ b/tests/unit_tests/core/test_diagram_generation.py @@ -25,6 +25,7 @@ import tests.unit_tests as unittest +import madgraph import madgraph.core.base_objects as base_objects import madgraph.core.color_amp as color_amp import madgraph.core.diagram_generation as diagram_generation @@ -4054,3 +4055,109 @@ def test_no_unrolling_without_quartic(self): amplitude = self.make_amplitude([5, -5], [5, -5]) self.assertEqual(amplitude.unroll_quartic_vertices(), {}) + +#=============================================================================== +# TestSeedRule +#=============================================================================== +class TestSeedRule(unittest.TestCase): + """Test the seed rule: no two cubic gluon vertices sharing a line. + + Unrolling a quartic vertex always yields two cubic vertices joined by the + line which replaced it, so the diagrams generation has to keep are exactly + those with no such pair to contract back.""" + + def setUp(self): + self.base_model = import_ufo.import_model('sm') + self.cubic_ids = diagram_generation.get_unrollable_cubic_ids( + self.base_model) + self.merge_quartic = madgraph.merge_quartic_vertices + + def tearDown(self): + madgraph.merge_quartic_vertices = self.merge_quartic + + def make_diagrams(self, initial, final, seed): + madgraph.merge_quartic_vertices = seed + myleglist = base_objects.LegList( + [base_objects.Leg({'id':pdg, 'state':False}) for pdg in initial] + + [base_objects.Leg({'id':pdg, 'state':True}) for pdg in final]) + return diagram_generation.Amplitude(base_objects.Process( + {'legs':myleglist, 'model':self.base_model})).get('diagrams') + + def cubic_adjacencies(self, diagram): + """Number of lines joining two cubic gluon vertices, counted without + any help from the generation. A line is recognised by its leg number + being live, a vertex reusing the smallest number coming in for the leg + it produces.""" + + vertices = diagram.get('vertices') + last = len(vertices) - 1 + live = {} + count = 0 + for i, vertex in enumerate(vertices): + legs = vertex.get('legs') + for leg in (legs if i == last else legs[:-1]): + producer = live.pop(leg.get('number'), None) + if producer is not None and \ + vertices[producer].get('id') in self.cubic_ids and \ + vertex.get('id') in self.cubic_ids: + count += 1 + if i != last: + live[legs[-1].get('number')] = i + self.assertFalse(live) + return count + + def check_process(self, initial, final, nfull, nseed): + """The generated seed has to be exactly the full generation filtered + on the rule -- same diagrams, not merely the same count.""" + + full = self.make_diagrams(initial, final, False) + seed = self.make_diagrams(initial, final, True) + self.assertEqual(len(full), nfull) + self.assertEqual(len(seed), nseed) + + def tags(diagrams): + return set(str(diagram_generation.UnrollDiagramTag( + diagram, self.base_model, len(initial))) + for diagram in diagrams) + + self.assertEqual(tags(seed), + tags([d for d in full + if not self.cubic_adjacencies(d)])) + self.assertFalse([d for d in seed if self.cubic_adjacencies(d)]) + + def test_seed_gg_gg(self): + """g g > g g: only the contact term has no cubic pair""" + + self.check_process([21, 21], [21, 21], 4, 1) + + def test_seed_gg_ggg(self): + """g g > g g g: the ten one quartic one cubic diagrams""" + + self.check_process([21, 21], [21, 21, 21], 25, 10) + + def test_seed_gg_gggg(self): + """g g > g g g g: 45 with a quartic in the middle, 10 with two""" + + self.check_process([21, 21], [21, 21, 21, 21], 220, 55) + + def test_seed_gg_ggggg(self): + """g g > g g g g g""" + + self.check_process([21, 21], [21, 21, 21, 21, 21], 2485, 385) + + def test_seed_gg_ttxgg(self): + """A cubic gluon vertex next to a quark line is not touched""" + + self.check_process([21, 21], [6, -6, 21, 21], 123, 84) + + def test_seed_inactive_by_default(self): + """Nothing changes unless madgraph.merge_quartic_vertices is set""" + + madgraph.merge_quartic_vertices = False + amplitude = diagram_generation.Amplitude(base_objects.Process( + {'legs':base_objects.LegList( + [base_objects.Leg({'id':21, 'state':False})] * 2 + + [base_objects.Leg({'id':21, 'state':True})] * 2), + 'model':self.base_model})) + self.assertEqual(amplitude.seed_forbidden_cubic_ids, frozenset()) + self.assertEqual(len(amplitude.get('diagrams')), 4) From 7da06bac7da9495268858a36b74d973abb5e011a Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 01:54:05 +0200 Subject: [PATCH 07/39] reconstruct the full diagram set by unrolling the seed The seed generated in the previous commit stands for the whole set: every diagram left out is one of its quartic vertices replaced by the pair of cubic vertices one of their colour structures factorises into. Expanding it back gives the baseline diagram list again, so nothing user-visible moves, and the unrolled diagram keeps the decomposition of the seed it came from -- which is the property the current sum needs, a quartic current and its cubic partner sharing every other current. Several seeds reach the same diagram, so the expansion dedups on the diagram itself. That has to be done on the glued form: while the identity vertex is still there the same diagram has several spellings, and a quartic vertex sitting just in front of it is not yet the last one -- which is what decides how ALOHA indexes its colour structures. Gluing it in right away, rather than at the end of generate_diagrams, settles both. Without it the expansion deduped nothing (40 diagrams for g g > g g g instead of 25) and the recorded colour chains disagreed with the colour algebra on 8 links out of 30. Expanding is confluent, so running the diagrams it produces through the same treatment adds nothing to the set but does give the link for the quartic vertices they have left, which is the whole map for free. process diagrams (= baseline) links |M|^2 vs baseline g g > g g 4 3 bit identical g g > g g g 25 30 bit identical g g > g g g g 220 405 1.5929925846563245e-04 vs ...3380e-04 g g > 5 g 2485 6300 6.6739867626784624e-07 vs ...4560e-07 Every link agrees, target for target, with the one the colour algebra gives independently through unroll_quartic_vertices. Co-Authored-By: Claude Opus 5 --- madgraph/core/diagram_generation.py | 167 ++++++++++++++++-- .../core/test_diagram_generation.py | 68 ++++++- 2 files changed, 214 insertions(+), 21 deletions(-) diff --git a/madgraph/core/diagram_generation.py b/madgraph/core/diagram_generation.py index 9dd7ba0916..c0e24e2548 100755 --- a/madgraph/core/diagram_generation.py +++ b/madgraph/core/diagram_generation.py @@ -525,6 +525,37 @@ def _f_pair_split(col_str): return pairs +def glued_vertices(diagram): + """Vertices of the diagram with the trailing identity vertex glued into + the one before it. + + The identity vertex only states that its two legs are the two ends of one + and the same line, so it is dropped once the diagram is complete, by + handing that line to the vertex before it. Until that is done the same + diagram can be written in several ways, and comparing two of them is + meaningless. Returns None when there is nothing to glue.""" + + vertices = diagram.get('vertices') + if len(vertices) <= 1 or vertices[-1].get('id') != 0: + return None + + vertices = copy.copy(vertices) + lastvx = vertices.pop() + nexttolastvertex = copy.copy(vertices.pop()) + legs = copy.copy(nexttolastvertex.get('legs')) + ntlnumber = legs[-1].get('number') + lastleg = [leg for leg in lastvx.get('legs') + if leg.get('number') != ntlnumber][0] + # Reset onshell in case we have forbidden s-channels + if lastleg.get('onshell') == False: + lastleg.set('onshell', None) + # Replace the last leg of nexttolastvertex + legs[-1] = lastleg + nexttolastvertex.set('legs', legs) + vertices.append(nexttolastvertex) + return vertices + + def get_unrollable_cubic_ids(model): """Interaction ids of the cubic vertices a factorisable quartic vertex unrolls into -- the three gluon vertex for the four gluon one.""" @@ -837,6 +868,8 @@ class Amplitude(base_objects.PhysicsObject): # share a line, see generate_diagrams. Empty -- so the rule is inactive -- # unless madgraph.merge_quartic_vertices is set. seed_forbidden_cubic_ids = frozenset() + # Links recorded while the seed was expanded, see expand_seed_diagrams + quartic_unroll_tags = {} def default_setup(self): """Default values for all properties""" @@ -1118,6 +1151,10 @@ def generate_diagrams(self, returndiag=False, diagram_filter=False): for vertex_list in reduced_leglist: res.append(self.create_diagram(base_objects.VertexList(vertex_list))) + # Put back the diagrams the seed rule left out + if self.seed_forbidden_cubic_ids: + res = self.expand_seed_diagrams(res) + # Record whether or not we failed generation before required # s-channel propagators are taken into account failed_crossing = not res @@ -1233,25 +1270,11 @@ def generate_diagrams(self, returndiag=False, diagram_filter=False): # Replace final id=0 vertex if necessary if not process.get('is_decay_chain'): for diagram in res: - vertices = diagram.get('vertices') - if len(vertices) > 1 and vertices[-1].get('id') == 0: - # Need to "glue together" last and next-to-last - # vertex, by replacing the (incoming) last leg of the - # next-to-last vertex with the (outgoing) leg in the - # last vertex - vertices = copy.copy(vertices) - lastvx = vertices.pop() - nexttolastvertex = copy.copy(vertices.pop()) - legs = copy.copy(nexttolastvertex.get('legs')) - ntlnumber = legs[-1].get('number') - lastleg = [leg for leg in lastvx.get('legs') if leg.get('number') != ntlnumber][0] - # Reset onshell in case we have forbidden s-channels - if lastleg.get('onshell') == False: - lastleg.set('onshell', None) - # Replace the last leg of nexttolastvertex - legs[-1] = lastleg - nexttolastvertex.set('legs', legs) - vertices.append(nexttolastvertex) + # "glue together" last and next-to-last vertex, by replacing + # the (incoming) last leg of the next-to-last vertex with the + # (outgoing) leg in the last vertex + vertices = glued_vertices(diagram) + if vertices is not None: diagram.set('vertices', vertices) if res and not returndiag: @@ -1355,6 +1378,112 @@ def remove_diag(diag, model=None): return res + def expand_seed_diagrams(self, seed): + """Put back the diagrams the seed rule left out of the generation. + + A seed diagram stands for itself and for every diagram obtained by + replacing any subset of its quartic vertices by the pair of cubic + vertices one of their colour structures factorises into. Several seeds + reach the same diagram, hence the dedup, and the result is the full + diagram set again -- same diagrams, same count, so nothing + user-visible moves. + + What the detour buys is the decomposition: an unrolled diagram is the + seed with one vertex taken apart, so it is rooted exactly like the + diagram it has to be summed with and shares every current except the + one being summed. + + Also records the link between a quartic contribution and the diagram + it unrolls to, see get_quartic_unroll_links. + """ + + model = self.get('process').get('model') + unrollable = get_unrollable_quartic_vertices(model) + ninitial = self.get_ninitial() + + def canonical_tag(diagram): + return str(UnrollDiagramTag(diagram, model, ninitial)) + + res = base_objects.DiagramList() + seen = set() + self.quartic_unroll_tags = {} + todo = [] + for diagram in seed: + # The identity vertex is glued in right away rather than at the + # end of generate_diagrams. Until it is, the same diagram has + # several spellings and comparing two of them is meaningless, and + # a quartic vertex sitting just before it is not yet the last one + # -- which is what decides how its colour structures are indexed. + vertices = glued_vertices(diagram) + if vertices is not None: + diagram = self.create_diagram(vertices) + tag = canonical_tag(diagram) + seen.add(tag) + res.append(diagram) + todo.append((diagram, tag)) + + # Unrolling is confluent, so taking the diagrams it produces through + # the same treatment adds nothing to the set -- but it does give the + # link for the quartic vertices they have left. + cursor = 0 + while cursor < len(todo): + diagram, own_tag = todo[cursor] + cursor += 1 + vertices = diagram.get('vertices') + positions = [i for i, vertex in enumerate(vertices) + if vertex.get('id') in unrollable] + if not positions: + continue + # None leaves the vertex alone, the other entries are the colour + # structures carrying a coupling, as kept by ColorBasis.colorize + allowed = [[None] + sorted(misc.make_unique( + [key[0] for key in model.get_interaction( + vertices[p].get('id')).get('couplings')])) + for p in positions] + + for keys in itertools.product(*allowed): + choice = dict((position, key) for position, key + in zip(positions, keys) if key is not None) + if not choice: + continue + unrolled = self.unrolled_diagram(diagram, choice, unrollable) + tag = canonical_tag(unrolled) + if tag not in seen: + seen.add(tag) + res.append(unrolled) + todo.append((unrolled, tag)) + if len(choice) == len(positions): + chain = tuple(choice.get(i, 0) + for i in range(len(vertices))) + self.quartic_unroll_tags[(own_tag, chain)] = tag + + return res + + def get_quartic_unroll_links(self, diaglist=None): + """Return {(diagram index, colour chain): target index} recorded while + the seed was expanded, resolved against the diagram list as it stands. + + This is the same map as the one unroll_quartic_vertices reconstructs + from the colour algebra, but obtained for free: the two diagrams are + one and the same seed unrolled differently. Empty when the diagrams + were not generated from a seed.""" + + if not self.quartic_unroll_tags: + return {} + + model = self.get('process').get('model') + if diaglist is None: + diaglist = self.get('diagrams') + ninitial = self.get_ninitial() + index = dict((str(UnrollDiagramTag(diagram, model, ninitial)), i) + for i, diagram in enumerate(diaglist)) + + res = {} + for (seed_tag, chain), tag in self.quartic_unroll_tags.items(): + if seed_tag in index and tag in index: + res[(index[seed_tag], chain)] = index[tag] + return res + def unroll_quartic_vertices(self, diaglist=None): """Link every quartic vertex contribution to the cubic diagram it merges with. diff --git a/tests/unit_tests/core/test_diagram_generation.py b/tests/unit_tests/core/test_diagram_generation.py index 750fc241f0..6ccc89d187 100755 --- a/tests/unit_tests/core/test_diagram_generation.py +++ b/tests/unit_tests/core/test_diagram_generation.py @@ -4076,12 +4076,24 @@ def tearDown(self): madgraph.merge_quartic_vertices = self.merge_quartic def make_diagrams(self, initial, final, seed): + """The generated diagrams, either the full set or -- with the seed + rule on and the expansion stopped -- the seed it starts from.""" + madgraph.merge_quartic_vertices = seed myleglist = base_objects.LegList( [base_objects.Leg({'id':pdg, 'state':False}) for pdg in initial] + [base_objects.Leg({'id':pdg, 'state':True}) for pdg in final]) - return diagram_generation.Amplitude(base_objects.Process( - {'legs':myleglist, 'model':self.base_model})).get('diagrams') + process = base_objects.Process({'legs':myleglist, + 'model':self.base_model}) + if not seed: + return diagram_generation.Amplitude(process).get('diagrams') + + class SeedOnlyAmplitude(diagram_generation.Amplitude): + """Stops after the seed, so that it can be looked at""" + def expand_seed_diagrams(self, seed): + return seed + + return SeedOnlyAmplitude(process).get('diagrams') def cubic_adjacencies(self, diagram): """Number of lines joining two cubic gluon vertices, counted without @@ -4150,6 +4162,58 @@ def test_seed_gg_ttxgg(self): self.check_process([21, 21], [6, -6, 21, 21], 123, 84) + def check_expansion(self, initial, final, nfull, nlink): + """Expanding the seed has to give the baseline diagram set back, and + the links it records have to be the ones the colour algebra gives.""" + + base = self.make_diagrams(initial, final, False) + madgraph.merge_quartic_vertices = True + myleglist = base_objects.LegList( + [base_objects.Leg({'id':pdg, 'state':False}) for pdg in initial] + + [base_objects.Leg({'id':pdg, 'state':True}) for pdg in final]) + amplitude = diagram_generation.Amplitude(base_objects.Process( + {'legs':myleglist, 'model':self.base_model})) + expanded = amplitude.get('diagrams') + + def tags(diagrams): + return set(str(diagram_generation.UnrollDiagramTag( + diagram, self.base_model, len(initial))) + for diagram in diagrams) + + # same diagrams, and no diagram reached twice + self.assertEqual(len(expanded), nfull) + self.assertEqual(len(base), nfull) + self.assertEqual(tags(expanded), tags(base)) + self.assertEqual(len(tags(expanded)), nfull) + + # the links recorded while expanding, and the independent ones + recorded = amplitude.get_quartic_unroll_links() + colour = amplitude.unroll_quartic_vertices() + self.assertEqual(len(recorded), nlink) + self.assertEqual(set(recorded), set(colour)) + for key, target in recorded.items(): + self.assertEqual(target, colour[key][0]) + + def test_expand_gg_gg(self): + """g g > g g: the contact term unrolls into s, t and u""" + + self.check_expansion([21, 21], [21, 21], 4, 3) + + def test_expand_gg_ggg(self): + """g g > g g g""" + + self.check_expansion([21, 21], [21, 21, 21], 25, 30) + + def test_expand_gg_gggg(self): + """g g > g g g g: 55 seeds reach all 220 diagrams""" + + self.check_expansion([21, 21], [21, 21, 21, 21], 220, 405) + + def test_expand_gg_ttxgg(self): + """Expansion leaves the quark lines alone""" + + self.check_expansion([21, 21], [6, -6, 21, 21], 123, 54) + def test_seed_inactive_by_default(self): """Nothing changes unless madgraph.merge_quartic_vertices is set""" From 0ad93275630bed0888d72ac3a5c1d11cb9e80cb7 Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 02:21:37 +0200 Subject: [PATCH 08/39] leave the seed rule off for decay chains A decay chain keeps its identity vertex rather than gluing it in, which is what the expansion relies on to compare two diagrams and to index the colour structures of a quartic vertex. Loop amplitudes were already excluded. Co-Authored-By: Claude Opus 5 --- docs/gluon-quartic-plan.md | 129 +++++++++++++++++++++++----- madgraph/core/diagram_generation.py | 6 +- 2 files changed, 111 insertions(+), 24 deletions(-) diff --git a/docs/gluon-quartic-plan.md b/docs/gluon-quartic-plan.md index 4f405e7b94..afaf34f1b9 100644 --- a/docs/gluon-quartic-plan.md +++ b/docs/gluon-quartic-plan.md @@ -66,6 +66,8 @@ property the whole optimisation needs. | `5c9cdb301` | why the current sums fail on the un-rewired DAG | | `1c1722ae8` | revert of the auxiliary-particle generation | | `98d288f41` | `reroot_diagram`, validated 755/755 — probably NOT needed under the seed rule | +| `25fc6d1cc` | step 1, the seed rule inside `reduce_leglist` | +| `1b9474f69` | step 2+3, `expand_seed_diagrams` and the recorded links | Useful pieces to keep: `get_unrollable_quartic_vertices`, `unroll_quartic_vertices`, `diagram_colour_signature`, `UnrollDiagramTag`, @@ -74,29 +76,110 @@ Useful pieces to keep: `get_unrollable_quartic_vertices`, ## Plan -**Step 1 — enforce the seed rule in generation.** Reject any combination that -puts two 3-gluon vertices on the same line, inside `reduce_leglist` / -`merge_comb_legs`. Verify the generated seed is exactly the filtered set -measured above (1 / 10 / 55 / 385). *Do not assume it is* — `from_group` -decides which combinations are offered and that interaction has been -mis-predicted before. - -**Step 2 — reconstruct the full set by unrolling the seed.** For every seed -diagram, every subset of its quartic vertices, every colour structure. Dedup -with `UnrollDiagramTag`. Gate: diagram count exactly equal to baseline -(4/25/220/2485) and `|M|^2` unchanged. A double count would hide here. - -**Step 3 — record the link during reconstruction.** Free: the quartic diagram -and its cubic partner are the same seed diagram unrolled differently. Replaces -the colour-vector matching, which stays as the independent cross-check. - -**Step 4 — the current sum.** Where a quartic current and its cubic partner -sit at the same node, emit `TMP = W1 + W4` and the subtree once. Prerequisite, -checked explicitly: their consumers must correspond 1:1 (see pitfall 6). - -**Step 5 — validate and time.** `|M|^2` for `g g > N g`, N=2..5 against -baseline; per-call timing with a driver looping `SMATRIX` (the shipped -`check_sa` measures startup, not the ME). +**Step 1 — enforce the seed rule in generation.** DONE, `25fc6d1cc`. Rejected +inside `reduce_leglist`, tracking by leg number which lines a cubic vertex +produced. Measured against the full generation filtered by an independently +written adjacency detector, comparing the diagrams and not only the counts: +1 / 10 / 55 / 385, and 4165 of 34300 at eight gluons. + +The closing vertex needs two cases, not one. A real n->0 interaction takes +the legs left over as lines coming in, but a 2->2 like reduction ends on the +*identity* vertex, which only states that its two legs are the two ends of +one line — and that line joins the two vertices which produced them. Missing +that left `g g > g g` with all four of its diagrams. + +**Step 2 — reconstruct the full set by unrolling the seed.** DONE, +`1b9474f69`, `expand_seed_diagrams`. Diagram count exactly the baseline +(4/25/220/2485), same diagrams by tag, `|M|^2` bit-identical at four and five +gluons and to 1e-14 at six and seven. + +The dedup has to run on the *glued* form. While the identity vertex is still +there the same diagram has several spellings, and a quartic vertex sitting +just in front of it is not yet the last one — which is what decides how ALOHA +indexes its colour structures. Without gluing first, the dedup caught nothing +(40 diagrams for `g g > g g g`) and 8 of 30 recorded colour chains disagreed +with the colour algebra. + +**Step 3 — record the link during reconstruction.** DONE, same commit, +`get_quartic_unroll_links`. 3 / 30 / 405 / 6300 links, every one agreeing +target for target with `unroll_quartic_vertices`, which stays as the +independent colour-algebra cross-check. + +**Step 4 — the current sum.** BLOCKED, and the reason is structural. Measured +on the reconstructed matrix element (`g g > g g g g`): of the 275 places where +a cubic current is fed by another cubic current *and* the quartic partner +taking the same four lines exists, 225 are the last vertex — the amplitude +sum, which pitfall 7 says buys nothing — and 50 are genuine currents. **None +of the 50 pass the 1:1 consumer test.** At seven gluons, none of 135. Only at +five gluons do all 7 pass. + +Why, from a failing pair: quartic current 30 has consumers +`{Wav(3,30), Amp(3,4,6,30)x3, Amp(6,8,30), Amp(4,10,30)}` while its cubic +partner 53 has `{Amp(6,8,53), Amp(4,10,53), Amp(3,12,53)}`. Two correspond; +the rest do not, because the same diagram is rooted differently on the two +sides. + +That is forced, not a bug in the reconstruction. Expanding the seed produces +more (seed, choice) unrollings than there are diagrams — about 340 for the +220 at six gluons — so some diagrams are reached from several seeds. A +diagram carries one decomposition, so it can be rooted to match at most one +of its quartic partners, while the current sum needs the match at *every* +node. Fact 3 above holds per (seed, choice) and breaks under the dedup that +fact 2 requires. Not fixable by choosing the spelling more cleverly: the +counting alone rules it out. + +What would work is a partial rewrite — build `TMP = W1 + W4` as a *third* +current, hand it only to the consumers which do correspond, and leave W1 and +W4 serving the rest. That splits shared consumers and cascades upward; it is +a DAG rewriting problem, not this plan. + +**Step 5 — validate and time.** DONE. `|M|^2` for `g g > N g`, N=2..5, and +per-call timing from the shipped `check` driver, which already loops +`SMATRIX` when given a second argument (`./check 1000 20000`). + +| | `g g > g g g g` | `g g > 5 g` | +|---|---|---| +| flag off | 47.73 / 47.77 s | 42.15 s | +| flag on, before steps 1-3 | 47.76 s | 40.86 s | +| flag on, at HEAD | 48.03 / 48.07 s | 40.41 s | + +and the code that produces it: + +| | helas calls | JAMP lines | +|---|---|---| +| flag off | 637 / 8159 | 1082 / 23672 | +| flag on, before steps 1-3 | 637 / 8159 | 688 / 8012 | +| flag on, at HEAD | 672 / 8216 | 688 / 7864 | + +So the flag is worth **+4.1% at seven gluons and -0.6% at six**, and nearly +all of that is the amplitude sum from `fcd8218b6` shrinking the JAMP block. +Steps 1-3 cost 35 helas calls at six gluons for nothing, and pay for +themselves only at seven (57 more calls, 148 fewer JAMP lines, net +1.1%). +The reconstruction deviates from the canonical decomposition, which is the +whole point, but it also weakens the wavefunction CSE — and without step 4 +there is nothing on the other side of that trade. + +With the flag off, `matrix.f` is byte-identical to `3b3ed9e85` for N=2..5. + +## Where to go next + +The current sum needs a node to have exactly one rooting *per merge*, which a +diagram list cannot give. Two ways out, both bigger than this plan: + +1. **Drop the diagram list for the currents.** Build the wavefunctions by a + Berends-Giele recursion over subsets — at each node, cubic pair plus + quartic, which generates exactly the matchings and never double counts — + and keep the 220 diagrams only for what they are actually needed for + (multichannel, `matrix.ps`). +2. **Partial CSE.** Keep the DAG, add `TMP = W1 + W4` alongside W1 and W4, + and split the consumers. Bounded gain: at six gluons only 2 of the 6 + quartic consumers correspond, so it saves 2 subtrees per node out of 50 + nodes. + +Anything that fragments the diagram list to get a per-rooting copy runs into +pitfall 1, and anything that expands each seed independently double counts — +the fully cubic diagrams get reached once per matching of their adjacency +graph (225 instead of 105 at six gluons). ## Pitfalls — all of these cost real time in the previous session diff --git a/madgraph/core/diagram_generation.py b/madgraph/core/diagram_generation.py index c0e24e2548..d0eafa14ea 100755 --- a/madgraph/core/diagram_generation.py +++ b/madgraph/core/diagram_generation.py @@ -1108,8 +1108,12 @@ def generate_diagrams(self, returndiag=False, diagram_filter=False): # yields two cubic vertices sharing the line which replaced it, so a # diagram can be reconstructed exactly when two of its cubic vertices # share a line -- and the seed is what is left over. + # Left off for a decay chain, whose identity vertex is kept rather + # than glued in, and for loop amplitudes, whose diagram set is not the + # one the unrolling reasons about. self.seed_forbidden_cubic_ids = frozenset() - if madgraph.merge_quartic_vertices and not self.has_loop_process(): + if madgraph.merge_quartic_vertices and not self.has_loop_process() \ + and not process.get('is_decay_chain'): self.seed_forbidden_cubic_ids = get_unrollable_cubic_ids(model) From 18fa381e2ad9e60ce0830527a2bfd96aad42ef01 Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 02:22:31 +0200 Subject: [PATCH 09/39] record what steps 1-5 measured, and why the current sum is blocked Steps 1, 2, 3 and 5 are done; step 4 is not, and the reason is a counting one rather than a bug. Expanding the seed makes 340 (seed, choice) instances for the 220 diagrams at six gluons, so a diagram is reached from several seeds, and since it carries one decomposition it can be rooted to match at most one of its quartic partners -- while the current sum needs the match at every node. Measured: of the 50 genuine current pairs at six gluons, none pass the 1:1 consumer test, and none of the 135 at seven; only five gluons, the size at which no diagram is reached twice, works. The flag as it stands is worth +4.1% at seven gluons and -0.6% at six, and nearly all of that is the amplitude sum shrinking the JAMP block. Co-Authored-By: Claude Opus 5 --- docs/gluon-quartic-plan.md | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/docs/gluon-quartic-plan.md b/docs/gluon-quartic-plan.md index afaf34f1b9..61b6dc8c81 100644 --- a/docs/gluon-quartic-plan.md +++ b/docs/gluon-quartic-plan.md @@ -120,13 +120,22 @@ the rest do not, because the same diagram is rooted differently on the two sides. That is forced, not a bug in the reconstruction. Expanding the seed produces -more (seed, choice) unrollings than there are diagrams — about 340 for the -220 at six gluons — so some diagrams are reached from several seeds. A -diagram carries one decomposition, so it can be rooted to match at most one +more (seed, choice) instances than there are diagrams, so some diagrams are +reached from several seeds: + +| process | seeds | (seed, choice) instances | diagrams | +|---|---|---|---| +| `g g > g g` | 1 | 4 | 4 | +| `g g > g g g` | 10 | 40 | 25 | +| `g g > g g g g` | 55 | 340 | 220 | +| `g g > 5 g` | 385 | 4900 | 2485 | + +A diagram carries one decomposition, so it can be rooted to match at most one of its quartic partners, while the current sum needs the match at *every* node. Fact 3 above holds per (seed, choice) and breaks under the dedup that fact 2 requires. Not fixable by choosing the spelling more cleverly: the -counting alone rules it out. +counting alone rules it out, and `g g > g g` — the one row with no collision +— is also the one process where the seed rule reaches every partner. What would work is a partial rewrite — build `TMP = W1 + W4` as a *third* current, hand it only to the consumers which do correspond, and leave W1 and From 8e634cf9ad3965a84660f31372e611ed89c6fce0 Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 07:02:35 +0200 Subject: [PATCH 10/39] sum the quartic current into the cubic one instead of the amplitude Where a quartic current and the cubic current carrying the same colour factor feed the same vertex, the two amplitudes they give differ by that one line and by nothing else. Summing the currents once and calling the amplitude on the sum gets both contributions out of a single call: W(20) = W(19) W(20)%W(:) = W(19)%W(:) + W(12)%W(:) CALL VVV1_0(W(4),W(5),W(20),GC_10,AMP(33)) instead of one VVV call for the cubic amplitude, one VVVV call for the quartic one, and an addition. The sum is shared by every amplitude reading it, so it pays for as many calls as it has users -- 60 amplitude calls for 30 sums at six gluons, 432 for 60 at seven. Substituting several mothers of the same amplitude also produces the amplitude with all of them substituted, so every subset has to be a merge into that same target weighing the product of the coefficients; the substitutions which do not pass are left as they were. That check is what keeps the count honest, and it is why the two-substitution cases at seven gluons are not taken: their other single is spelled with a different rooting and is not the same amplitude object. The slot reuse had to be told about it. reuse_outdated_wavefunctions works out when a slot is free from the diagrams alone, and the sum is an extra read it cannot see -- without that, the two currents were handed the same slot and the line came out as W(11) + W(11). process helas calls JAMP lines per-call time g g > g g g 94 -> 93 + 7 131 -> 101 34.88 -> 35.12 s g g > g g g g 637 -> 612 + 30 1082 -> 688 47.77 -> 46.02 s g g > 5 g 8159 ->7784 + 60 23672 -> 7864 42.16 -> 39.80 s so +3.8% at six gluons and +5.6% at seven, where the seed reconstruction alone had been worth -0.6% and +4.1%. |M|^2 bit-identical at four and five gluons, 1e-15 at six and seven, and unchanged for g g > t t~ g g and u u~ > g g g. With the flag off matrix.f is byte-identical to before. Co-Authored-By: Claude Opus 5 --- UNITTEST_proc/Cards/MadLoopParams.dat | 298 ++ UNITTEST_proc/Cards/MadLoopParams_default.dat | 298 ++ UNITTEST_proc/Cards/ident_card.dat | 35 + UNITTEST_proc/Cards/param_card.dat | 93 + UNITTEST_proc/Cards/param_card_default.dat | 93 + UNITTEST_proc/MGMEVersion.txt | 1 + UNITTEST_proc/Source/DHELAS/FFV1LP0_3.f | 29 + UNITTEST_proc/Source/DHELAS/FFV1L_1.f | 51 + UNITTEST_proc/Source/DHELAS/FFV1L_2.f | 51 + UNITTEST_proc/Source/DHELAS/FFV1P0_3.f | 40 + UNITTEST_proc/Source/DHELAS/FFV1_0.f | 33 + UNITTEST_proc/Source/DHELAS/FFV1_1.f | 55 + UNITTEST_proc/Source/DHELAS/FFV1_2.f | 55 + UNITTEST_proc/Source/DHELAS/GHGHGL_1.f | 25 + UNITTEST_proc/Source/DHELAS/GHGHGL_2.f | 25 + UNITTEST_proc/Source/DHELAS/MP_FFV1LP0_3.f | 29 + UNITTEST_proc/Source/DHELAS/MP_FFV1L_1.f | 51 + UNITTEST_proc/Source/DHELAS/MP_FFV1L_2.f | 51 + UNITTEST_proc/Source/DHELAS/MP_FFV1P0_3.f | 40 + UNITTEST_proc/Source/DHELAS/MP_FFV1_0.f | 33 + UNITTEST_proc/Source/DHELAS/MP_FFV1_1.f | 55 + UNITTEST_proc/Source/DHELAS/MP_FFV1_2.f | 55 + UNITTEST_proc/Source/DHELAS/MP_GHGHGL_1.f | 25 + UNITTEST_proc/Source/DHELAS/MP_GHGHGL_2.f | 25 + UNITTEST_proc/Source/DHELAS/MP_R2_GG_1_0.f | 24 + .../Source/DHELAS/MP_R2_GG_1_R2_GG_2_0.f | 31 + .../Source/DHELAS/MP_R2_GG_1_R2_GG_3_0.f | 25 + UNITTEST_proc/Source/DHELAS/MP_R2_GG_2_0.f | 25 + UNITTEST_proc/Source/DHELAS/MP_R2_GG_3_0.f | 20 + UNITTEST_proc/Source/DHELAS/MP_R2_QQ_1_0.f | 33 + .../Source/DHELAS/MP_R2_QQ_1_R2_QQ_2_0.f | 37 + UNITTEST_proc/Source/DHELAS/MP_R2_QQ_2_0.f | 28 + UNITTEST_proc/Source/DHELAS/MP_VVV1LP0_1.f | 49 + UNITTEST_proc/Source/DHELAS/MP_VVV1P0_1.f | 52 + UNITTEST_proc/Source/DHELAS/MP_VVV1_0.f | 53 + UNITTEST_proc/Source/DHELAS/MP_VVVV1LP0_1.f | 30 + UNITTEST_proc/Source/DHELAS/MP_VVVV3LP0_1.f | 30 + UNITTEST_proc/Source/DHELAS/MP_VVVV4LP0_1.f | 30 + UNITTEST_proc/Source/DHELAS/R2_GG_1_0.f | 24 + .../Source/DHELAS/R2_GG_1_R2_GG_2_0.f | 31 + .../Source/DHELAS/R2_GG_1_R2_GG_3_0.f | 25 + UNITTEST_proc/Source/DHELAS/R2_GG_2_0.f | 25 + UNITTEST_proc/Source/DHELAS/R2_GG_3_0.f | 20 + UNITTEST_proc/Source/DHELAS/R2_QQ_1_0.f | 33 + .../Source/DHELAS/R2_QQ_1_R2_QQ_2_0.f | 37 + UNITTEST_proc/Source/DHELAS/R2_QQ_2_0.f | 28 + UNITTEST_proc/Source/DHELAS/VVV1LP0_1.f | 49 + UNITTEST_proc/Source/DHELAS/VVV1P0_1.f | 52 + UNITTEST_proc/Source/DHELAS/VVV1_0.f | 53 + UNITTEST_proc/Source/DHELAS/VVVV1LP0_1.f | 30 + UNITTEST_proc/Source/DHELAS/VVVV3LP0_1.f | 30 + UNITTEST_proc/Source/DHELAS/VVVV4LP0_1.f | 30 + UNITTEST_proc/Source/DHELAS/aloha_file.inc | 1 + UNITTEST_proc/Source/DHELAS/aloha_functions.f | 3044 +++++++++++++++++ UNITTEST_proc/Source/DHELAS/makefile | 40 + .../Source/MODEL/actualize_mp_ext_params.inc | 7 + UNITTEST_proc/Source/MODEL/coupl.inc | 47 + UNITTEST_proc/Source/MODEL/coupl_write.inc | 35 + UNITTEST_proc/Source/MODEL/couplings.f | 158 + UNITTEST_proc/Source/MODEL/couplings1.f | 16 + UNITTEST_proc/Source/MODEL/couplings2.f | 16 + UNITTEST_proc/Source/MODEL/couplings3.f | 68 + UNITTEST_proc/Source/MODEL/flavor_couplings.f | 30 + UNITTEST_proc/Source/MODEL/formats.inc | 30 + UNITTEST_proc/Source/MODEL/get_color.f | 158 + UNITTEST_proc/Source/MODEL/input.inc | 44 + .../Source/MODEL/intparam_definition.inc | 196 ++ UNITTEST_proc/Source/MODEL/lha_read.f | 486 +++ UNITTEST_proc/Source/MODEL/makefile | 56 + UNITTEST_proc/Source/MODEL/makeinc.inc | 5 + UNITTEST_proc/Source/MODEL/model_functions.f | 1038 ++++++ .../Source/MODEL/model_functions.inc | 32 + UNITTEST_proc/Source/MODEL/mp_coupl.inc | 44 + .../Source/MODEL/mp_coupl_same_name.inc | 37 + UNITTEST_proc/Source/MODEL/mp_couplings1.f | 16 + UNITTEST_proc/Source/MODEL/mp_couplings2.f | 16 + UNITTEST_proc/Source/MODEL/mp_couplings3.f | 80 + UNITTEST_proc/Source/MODEL/mp_input.inc | 56 + .../Source/MODEL/mp_intparam_definition.inc | 210 ++ .../Source/MODEL/param_card_rule.dat | 25 + UNITTEST_proc/Source/MODEL/param_read.inc | 57 + UNITTEST_proc/Source/MODEL/param_write.inc | 100 + UNITTEST_proc/Source/MODEL/printout.f | 40 + UNITTEST_proc/Source/MODEL/rw_para.f | 97 + UNITTEST_proc/Source/MODEL/testprog.f | 72 + UNITTEST_proc/Source/coupl.inc | 1 + UNITTEST_proc/Source/make_opts | 132 + UNITTEST_proc/Source/makefile | 96 + .../ML5_0_ColorDenomFactors.dat | 129 + .../ML5_0_ColorNumFactors.dat | 129 + .../MadLoop5_resources/ML5_0_HelConfigs.dat | 16 + .../MadLoop5_resources/MadLoopParams.dat | 1 + .../MadLoop5_resources/ident_card.dat | 1 + .../MadLoop5_resources/param_card.dat | 1 + UNITTEST_proc/SubProcesses/MadLoopCommons.f | 682 ++++ .../SubProcesses/MadLoopParamReader.f | 343 ++ UNITTEST_proc/SubProcesses/MadLoopParams.dat | 1 + UNITTEST_proc/SubProcesses/MadLoopParams.inc | 30 + .../SubProcesses/MadLoop_makefile_definitions | 13 + .../SubProcesses/P0_gg_ttx/CT_interface.f | 663 ++++ .../SubProcesses/P0_gg_ttx/MadLoop5_resources | 1 + .../SubProcesses/P0_gg_ttx/MadLoopCommons.f | 1 + .../P0_gg_ttx/MadLoopParamReader.f | 1 + .../SubProcesses/P0_gg_ttx/MadLoopParams.inc | 1 + .../SubProcesses/P0_gg_ttx/born_matrix.f | 989 ++++++ .../SubProcesses/P0_gg_ttx/born_matrix.ps | Bin 0 -> 13824 bytes .../SubProcesses/P0_gg_ttx/check_sa.f | 746 ++++ .../SubProcesses/P0_gg_ttx/coupl.inc | 1 + .../SubProcesses/P0_gg_ttx/cts_mpc.h | 1 + .../SubProcesses/P0_gg_ttx/cts_mprec.h | 1 + .../SubProcesses/P0_gg_ttx/global_specs.inc | 1 + .../SubProcesses/P0_gg_ttx/improve_ps.f | 1014 ++++++ .../SubProcesses/P0_gg_ttx/loop_matrix.f | 1860 ++++++++++ .../SubProcesses/P0_gg_ttx/loop_matrix.ps | Bin 0 -> 46706 bytes .../SubProcesses/P0_gg_ttx/loop_num.f | 934 +++++ UNITTEST_proc/SubProcesses/P0_gg_ttx/makefile | 1 + .../SubProcesses/P0_gg_ttx/mg5_citation.f | 1 + .../P0_gg_ttx/mp_born_amps_and_wfs.f | 282 ++ .../SubProcesses/P0_gg_ttx/mp_coupl.inc | 1 + .../P0_gg_ttx/mp_coupl_same_name.inc | 1 + .../SubProcesses/P0_gg_ttx/nexternal.inc | 4 + .../SubProcesses/P0_gg_ttx/ngraphs.inc | 2 + .../SubProcesses/P0_gg_ttx/nsquaredSO.inc | 2 + .../SubProcesses/P0_gg_ttx/pmass.inc | 4 + .../SubProcesses/P0_gg_ttx/unique_id.inc | 2 + UNITTEST_proc/SubProcesses/coupl.inc | 1 + UNITTEST_proc/SubProcesses/cts_mpc.h | 2 + UNITTEST_proc/SubProcesses/cts_mprec.h | 2 + UNITTEST_proc/SubProcesses/makefile | 201 ++ UNITTEST_proc/SubProcesses/makefileP | 55 + UNITTEST_proc/SubProcesses/mg5_citation.f | 91 + UNITTEST_proc/SubProcesses/mp_coupl.inc | 1 + .../SubProcesses/mp_coupl_same_name.inc | 1 + UNITTEST_proc/TemplateVersion.txt | 1 + madgraph/core/helas_objects.py | 207 +- madgraph/iolibs/helas_call_writers.py | 93 +- .../core/test_diagram_generation.py | 84 + 137 files changed, 17656 insertions(+), 9 deletions(-) create mode 100644 UNITTEST_proc/Cards/MadLoopParams.dat create mode 100644 UNITTEST_proc/Cards/MadLoopParams_default.dat create mode 100644 UNITTEST_proc/Cards/ident_card.dat create mode 100644 UNITTEST_proc/Cards/param_card.dat create mode 100644 UNITTEST_proc/Cards/param_card_default.dat create mode 100644 UNITTEST_proc/MGMEVersion.txt create mode 100644 UNITTEST_proc/Source/DHELAS/FFV1LP0_3.f create mode 100644 UNITTEST_proc/Source/DHELAS/FFV1L_1.f create mode 100644 UNITTEST_proc/Source/DHELAS/FFV1L_2.f create mode 100644 UNITTEST_proc/Source/DHELAS/FFV1P0_3.f create mode 100644 UNITTEST_proc/Source/DHELAS/FFV1_0.f create mode 100644 UNITTEST_proc/Source/DHELAS/FFV1_1.f create mode 100644 UNITTEST_proc/Source/DHELAS/FFV1_2.f create mode 100644 UNITTEST_proc/Source/DHELAS/GHGHGL_1.f create mode 100644 UNITTEST_proc/Source/DHELAS/GHGHGL_2.f create mode 100644 UNITTEST_proc/Source/DHELAS/MP_FFV1LP0_3.f create mode 100644 UNITTEST_proc/Source/DHELAS/MP_FFV1L_1.f create mode 100644 UNITTEST_proc/Source/DHELAS/MP_FFV1L_2.f create mode 100644 UNITTEST_proc/Source/DHELAS/MP_FFV1P0_3.f create mode 100644 UNITTEST_proc/Source/DHELAS/MP_FFV1_0.f create mode 100644 UNITTEST_proc/Source/DHELAS/MP_FFV1_1.f create mode 100644 UNITTEST_proc/Source/DHELAS/MP_FFV1_2.f create mode 100644 UNITTEST_proc/Source/DHELAS/MP_GHGHGL_1.f create mode 100644 UNITTEST_proc/Source/DHELAS/MP_GHGHGL_2.f create mode 100644 UNITTEST_proc/Source/DHELAS/MP_R2_GG_1_0.f create mode 100644 UNITTEST_proc/Source/DHELAS/MP_R2_GG_1_R2_GG_2_0.f create mode 100644 UNITTEST_proc/Source/DHELAS/MP_R2_GG_1_R2_GG_3_0.f create mode 100644 UNITTEST_proc/Source/DHELAS/MP_R2_GG_2_0.f create mode 100644 UNITTEST_proc/Source/DHELAS/MP_R2_GG_3_0.f create mode 100644 UNITTEST_proc/Source/DHELAS/MP_R2_QQ_1_0.f create mode 100644 UNITTEST_proc/Source/DHELAS/MP_R2_QQ_1_R2_QQ_2_0.f create mode 100644 UNITTEST_proc/Source/DHELAS/MP_R2_QQ_2_0.f create mode 100644 UNITTEST_proc/Source/DHELAS/MP_VVV1LP0_1.f create mode 100644 UNITTEST_proc/Source/DHELAS/MP_VVV1P0_1.f create mode 100644 UNITTEST_proc/Source/DHELAS/MP_VVV1_0.f create mode 100644 UNITTEST_proc/Source/DHELAS/MP_VVVV1LP0_1.f create mode 100644 UNITTEST_proc/Source/DHELAS/MP_VVVV3LP0_1.f create mode 100644 UNITTEST_proc/Source/DHELAS/MP_VVVV4LP0_1.f create mode 100644 UNITTEST_proc/Source/DHELAS/R2_GG_1_0.f create mode 100644 UNITTEST_proc/Source/DHELAS/R2_GG_1_R2_GG_2_0.f create mode 100644 UNITTEST_proc/Source/DHELAS/R2_GG_1_R2_GG_3_0.f create mode 100644 UNITTEST_proc/Source/DHELAS/R2_GG_2_0.f create mode 100644 UNITTEST_proc/Source/DHELAS/R2_GG_3_0.f create mode 100644 UNITTEST_proc/Source/DHELAS/R2_QQ_1_0.f create mode 100644 UNITTEST_proc/Source/DHELAS/R2_QQ_1_R2_QQ_2_0.f create mode 100644 UNITTEST_proc/Source/DHELAS/R2_QQ_2_0.f create mode 100644 UNITTEST_proc/Source/DHELAS/VVV1LP0_1.f create mode 100644 UNITTEST_proc/Source/DHELAS/VVV1P0_1.f create mode 100644 UNITTEST_proc/Source/DHELAS/VVV1_0.f create mode 100644 UNITTEST_proc/Source/DHELAS/VVVV1LP0_1.f create mode 100644 UNITTEST_proc/Source/DHELAS/VVVV3LP0_1.f create mode 100644 UNITTEST_proc/Source/DHELAS/VVVV4LP0_1.f create mode 100644 UNITTEST_proc/Source/DHELAS/aloha_file.inc create mode 100644 UNITTEST_proc/Source/DHELAS/aloha_functions.f create mode 100644 UNITTEST_proc/Source/DHELAS/makefile create mode 100644 UNITTEST_proc/Source/MODEL/actualize_mp_ext_params.inc create mode 100644 UNITTEST_proc/Source/MODEL/coupl.inc create mode 100644 UNITTEST_proc/Source/MODEL/coupl_write.inc create mode 100644 UNITTEST_proc/Source/MODEL/couplings.f create mode 100644 UNITTEST_proc/Source/MODEL/couplings1.f create mode 100644 UNITTEST_proc/Source/MODEL/couplings2.f create mode 100644 UNITTEST_proc/Source/MODEL/couplings3.f create mode 100644 UNITTEST_proc/Source/MODEL/flavor_couplings.f create mode 100644 UNITTEST_proc/Source/MODEL/formats.inc create mode 100644 UNITTEST_proc/Source/MODEL/get_color.f create mode 100644 UNITTEST_proc/Source/MODEL/input.inc create mode 100644 UNITTEST_proc/Source/MODEL/intparam_definition.inc create mode 100644 UNITTEST_proc/Source/MODEL/lha_read.f create mode 100644 UNITTEST_proc/Source/MODEL/makefile create mode 100644 UNITTEST_proc/Source/MODEL/makeinc.inc create mode 100644 UNITTEST_proc/Source/MODEL/model_functions.f create mode 100644 UNITTEST_proc/Source/MODEL/model_functions.inc create mode 100644 UNITTEST_proc/Source/MODEL/mp_coupl.inc create mode 100644 UNITTEST_proc/Source/MODEL/mp_coupl_same_name.inc create mode 100644 UNITTEST_proc/Source/MODEL/mp_couplings1.f create mode 100644 UNITTEST_proc/Source/MODEL/mp_couplings2.f create mode 100644 UNITTEST_proc/Source/MODEL/mp_couplings3.f create mode 100644 UNITTEST_proc/Source/MODEL/mp_input.inc create mode 100644 UNITTEST_proc/Source/MODEL/mp_intparam_definition.inc create mode 100644 UNITTEST_proc/Source/MODEL/param_card_rule.dat create mode 100644 UNITTEST_proc/Source/MODEL/param_read.inc create mode 100644 UNITTEST_proc/Source/MODEL/param_write.inc create mode 100644 UNITTEST_proc/Source/MODEL/printout.f create mode 100644 UNITTEST_proc/Source/MODEL/rw_para.f create mode 100644 UNITTEST_proc/Source/MODEL/testprog.f create mode 120000 UNITTEST_proc/Source/coupl.inc create mode 100644 UNITTEST_proc/Source/make_opts create mode 100644 UNITTEST_proc/Source/makefile create mode 100644 UNITTEST_proc/SubProcesses/MadLoop5_resources/ML5_0_ColorDenomFactors.dat create mode 100644 UNITTEST_proc/SubProcesses/MadLoop5_resources/ML5_0_ColorNumFactors.dat create mode 100644 UNITTEST_proc/SubProcesses/MadLoop5_resources/ML5_0_HelConfigs.dat create mode 120000 UNITTEST_proc/SubProcesses/MadLoop5_resources/MadLoopParams.dat create mode 120000 UNITTEST_proc/SubProcesses/MadLoop5_resources/ident_card.dat create mode 120000 UNITTEST_proc/SubProcesses/MadLoop5_resources/param_card.dat create mode 100644 UNITTEST_proc/SubProcesses/MadLoopCommons.f create mode 100644 UNITTEST_proc/SubProcesses/MadLoopParamReader.f create mode 120000 UNITTEST_proc/SubProcesses/MadLoopParams.dat create mode 100644 UNITTEST_proc/SubProcesses/MadLoopParams.inc create mode 100644 UNITTEST_proc/SubProcesses/MadLoop_makefile_definitions create mode 100644 UNITTEST_proc/SubProcesses/P0_gg_ttx/CT_interface.f create mode 120000 UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoop5_resources create mode 120000 UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoopCommons.f create mode 120000 UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoopParamReader.f create mode 120000 UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoopParams.inc create mode 100644 UNITTEST_proc/SubProcesses/P0_gg_ttx/born_matrix.f create mode 100644 UNITTEST_proc/SubProcesses/P0_gg_ttx/born_matrix.ps create mode 100644 UNITTEST_proc/SubProcesses/P0_gg_ttx/check_sa.f create mode 120000 UNITTEST_proc/SubProcesses/P0_gg_ttx/coupl.inc create mode 120000 UNITTEST_proc/SubProcesses/P0_gg_ttx/cts_mpc.h create mode 120000 UNITTEST_proc/SubProcesses/P0_gg_ttx/cts_mprec.h create mode 120000 UNITTEST_proc/SubProcesses/P0_gg_ttx/global_specs.inc create mode 100644 UNITTEST_proc/SubProcesses/P0_gg_ttx/improve_ps.f create mode 100644 UNITTEST_proc/SubProcesses/P0_gg_ttx/loop_matrix.f create mode 100644 UNITTEST_proc/SubProcesses/P0_gg_ttx/loop_matrix.ps create mode 100644 UNITTEST_proc/SubProcesses/P0_gg_ttx/loop_num.f create mode 120000 UNITTEST_proc/SubProcesses/P0_gg_ttx/makefile create mode 120000 UNITTEST_proc/SubProcesses/P0_gg_ttx/mg5_citation.f create mode 100644 UNITTEST_proc/SubProcesses/P0_gg_ttx/mp_born_amps_and_wfs.f create mode 120000 UNITTEST_proc/SubProcesses/P0_gg_ttx/mp_coupl.inc create mode 120000 UNITTEST_proc/SubProcesses/P0_gg_ttx/mp_coupl_same_name.inc create mode 100644 UNITTEST_proc/SubProcesses/P0_gg_ttx/nexternal.inc create mode 100644 UNITTEST_proc/SubProcesses/P0_gg_ttx/ngraphs.inc create mode 100644 UNITTEST_proc/SubProcesses/P0_gg_ttx/nsquaredSO.inc create mode 100644 UNITTEST_proc/SubProcesses/P0_gg_ttx/pmass.inc create mode 100644 UNITTEST_proc/SubProcesses/P0_gg_ttx/unique_id.inc create mode 120000 UNITTEST_proc/SubProcesses/coupl.inc create mode 100644 UNITTEST_proc/SubProcesses/cts_mpc.h create mode 100644 UNITTEST_proc/SubProcesses/cts_mprec.h create mode 100644 UNITTEST_proc/SubProcesses/makefile create mode 100644 UNITTEST_proc/SubProcesses/makefileP create mode 100644 UNITTEST_proc/SubProcesses/mg5_citation.f create mode 120000 UNITTEST_proc/SubProcesses/mp_coupl.inc create mode 120000 UNITTEST_proc/SubProcesses/mp_coupl_same_name.inc create mode 100644 UNITTEST_proc/TemplateVersion.txt diff --git a/UNITTEST_proc/Cards/MadLoopParams.dat b/UNITTEST_proc/Cards/MadLoopParams.dat new file mode 100644 index 0000000000..425d909582 --- /dev/null +++ b/UNITTEST_proc/Cards/MadLoopParams.dat @@ -0,0 +1,298 @@ +! This file is for the user to set the different parameters of MadLoop. +! The name of the variable to define must start with the '#' sign and then +! the value should be put immediately on the next line. + +! +#MLReductionLib +!6|7|1 +! Default :: 6|7|1 +! The tensor integral reduction library.The current choices are: +! 1 | CutTools +! 2 | PJFry++ +! 3 | IREGI +! 4 | Golem95 +! 5 | Samurai +! 6 | Ninja +! 7 | COLLIER +! One can use the combinations to reduce integral,e.g. +! 1|2|3 means first use CutTools, if it is not stable, use PJFry++, +! if it is still unstable, use IREGI. If it failed, use QP of CutTools. +! Notice that any reduction tool not avaialble on the system will be automatically +! skipped. + +! When using quadruple precision with Ninja or CutTools, the reduction will +! always be done in quadruple precision, but the parameters below allow you to +! chose if you want to also recompute the *integrand* in quadruple precision. +! Doing so is slow but might improve the accuracy in some situation. +#UseQPIntegrandForCutTools +!.TRUE. +! Default :: .TRUE. +#UseQPIntegrandForNinja +!.TRUE. +! Default :: .TRUE. +! + +! ================================================================================= +! The parameters below set the parameters for IREGI +! ================================================================================= + +#IREGIMODE +!2 +! Default :: 2 +! IREGIMODE=0, IBP reduction +! IREGIMODE=1, PaVe reduction +! IREGIMODE=2, PaVe reduction with stablility improved by IBP reduction + +#IREGIRECY +!.TRUE. +! Default :: .TRUE. +! Use RECYCLING OR NOT IN IREGI +! + +! ================================================================================= +! The parameters below set the stability checks of MadLoop at run time +! ================================================================================= + +! Decide in which mode to run MadLoop +! +! imode:| description +! 1 | Double precision, loops reduced with propagator in original order +! 2 | Double precision, loops reduced with propagator with reversed order +! 4 | Quadruple precision, loops reduced with propagator in original order +! 5 | Quadruple precision, loops reduced with propagator with reversed order +! -1 | Exhaustive automated numerical stability checks. See below for details. +! +! Due to the architecture of the program, you are better off +! rerunning the full PS point in quadruple precision than just a single loop +! because the two things would almost take the same time. So '-1' is always +! very recommended. +#CTModeRun +!-1 +! Default :: -1 +! In the negative mode -1, MadLoop first evaluates each PS points in modes 1 and 2, +! yielding results Res1 and Res2, and then check if: +! (Res1-Res2)/(2*(Res1+Res2)< MLStabThres +! If it is not the case, MadLoop evaluates again the PS point in modes 4 and 5, +! yielding results Res4 and Res5, and then check if: +! (Res4-Res5)/(2*(Res4+Res5)< MLStabThres +! If it is the case then the unstable phase-space point could be cured. If it is +! not the case, MadLoop outputs a warning. +! Notice that MLStabThres is used only when CTModeRun is negative. +#MLStabThres +!1.0d-3 +! Default :: 1.0d-3 +! You can add other evaluation method to check for the stability in DP and QP. +! Below you can chose if you want to use zero, one or two rotations of the PS point +! in QP. +#NRotations_DP +!0 +! Default :: 0 +#NRotations_QP +!0 +! Default :: 0 + +! By default, MadLoop is allowed to slightly deform the Phase-Space point in input +! so to insure perfect onshellness of the external particles and perfect energy-momentum +! conservation. The deformation is minimal and such that it leaves the input PS point +! unchanged if it already satisfies the physical condiditions mentioned above. +! This integer values select what is the method to be employed preferably to restore this +! precision. It can take the following values: +! +! -1 :: No method is used for double precision computations, and method 2 will be used +! preferentially when quadruple precision (for which this precision improvement +! is mandatory, otherwise quadruple precision is pointless) +! 1 :: This methods imitates what is done in PSMC, namely +! a) Set the space-like momentum of the last external particle to be the +! opposite of the sum of the others (with a minus sign for the initial states). +! b) Rescale all final state space-like momenta by a fixed value x computed such +! that energy is conserved when particles are put exactly onshell. This value +! is determined numericaly via Ralph-Newton's method. +! c) Set all energies to have particles exactly onshell. +! 2 :: This method applies a shift to the energy and the x and y components of the first +! initial state momentum in order to restore exact energy momentum conservation after +! particles have been put exactly onshell via a shift of the z component of their +! momenta. +#ImprovePSPoint +!2 +! Default :: 2 + +! ================================================================================= +! The parameters below set two CutTools internal parameters accessible to the user. +! ================================================================================= + +! Choose here what library to chose for CutTools/TIR to compute the scalar loops of the +! master integral basis. The choices are as follows: +! (Does not apply for Golem95, where OneLOop is always used) +! 2 | OneLOop +! 3 | QCDLoop +#CTLoopLibrary +!2 +! Default :: 2 + +! Choose here the stability threshold used within CutTools to decide when to go to +! higher precision. +#CTStabThres +!1.0d-2 +! Default :: 1.0d-2 + +! ================================================================================= +! The parameters below set the general behavior of MadLoop for the initialization +! ================================================================================= + +! Decide in which mode to run when performing MadLoop's initialization of +! the helicity (and possibly loop) filter. The possible modes are: +! +! Decide in which mode to run MadLoop +! +! imode:| description +! 1 | Double precision, loops reduced with propagator in original order +! 2 | Double precision, loops reduced with propagator with reversed order +! 4 | Quadruple precision, loops reduced with propagator in original order +! 5 | Quadruple precision, loops reduced with propagator with reversed order +! +#CTModeInit +!1 +! Default :: 1 + +! CheckCycle sets on how many PS points trials the initialization filters must be +! obtained. As long as MadLoop does not find that many consecutive PS points for +! which the filters are the same, it will start over but only a maximum of +! MaxAttempts times. +#CheckCycle +!3 +! Default :: 3 +#MaxAttempts +!10 +! Default :: 10 + +! Setting the threshold for deciding wether a numerical contribution is analytically +! zero or not. +#ZeroThres +!1.0d-9 +! Default :: 1.0d-9 + +! Setting the on-shell threshold for deciding whether the invariant variables +! of external momenta are on-shell or not. It will only be used in constructing +! s-matrix in Golem95. +#OSThres +!1.0d-8 +! Default :: 1.0d-8 + +! The setting below is recommended to be on as it allows to systematically used the +! first PS point thrown at ML5 to be used for making sure that the helicity filter +! read from HelFilter.dat is consistent as it might be no longer up to date with +! certain changes of the paramaters by the user. +#DoubleCheckHelicityFilter +!.TRUE. +! Default :: .TRUE. + +! This decides whether to write out the helicity and loop filters to the files +! HelFilters.dat and LoopFilters.dat to save them for future runs. It usually +! preferable but sometimes not desired because of the need of threadlocks in the +! context of mpi parallelization. So it can be turned off here in such cases. +#WriteOutFilters +!.TRUE. +! Default :: .TRUE. + +! Some loop contributions may be zero for some helicities which are however +! contributing. In order to save their computing time, you can chose here to try +! to filter them out. The gain is typically minimal, so it is turned off by default. +#UseLoopFilter +!.FALSE. +! Default :: .FALSE. + +! The integer below set at which level the user wants to filter helicity configuration. +! Notice that this does not entail any approximation. It only offers the possibility of +! performing exact simplifications based on numerical checks. HelicityFilterLevel = +! 0 : No filtering at all. Not HelFilter.dat file will be written out and *all* helicity +! configurations will be computed. +! 1 : Analytically zero helicity configurations will be recognized as such by numerical +! comparisons (using the 'ZeroThres' param) and consistently skipped in further +! computations. +! 2 : Filters both helicity configuration which are analytically zero *and* those +! consistently identical (typically because of CP symmetry). +! (Will only effectively do it if process was generated in 'optimized_mode') +#HelicityFilterLevel +!2 +! Default :: 2 + +! This decides whether consecutive consistency for the loop filtering setup is also +! required. +#LoopInitStartOver +!.FALSE. +! Default :: .FALSE. + +! This decides wether consecutive consistency for the helicity filtering setup is also +! required. Better to set it to false as it can cause problems for unstable processes. +#HelInitStartOver +!.FALSE. +! Default :: .FALSE. + +! ================================================================================= +! The parameters below set the main parameters for COLLIER +! To edit more specific technical COLLIER parameters, modify directly the content +! of the subroutine 'INITCOLLIER' in the file 'MadLoopCommons.f' +! ================================================================================= + +! Decide if COLLIER must be computed multiple times to evaluate the UV pole residues +! (Withing a Monte-Carlo performed in MG5aMC, this is automatically disabled internally) +#COLLIERComputeUVpoles +!.TRUE. +! Default :: .TRUE. + +! Decide if COLLIER must be computed multiple times to evaluate the IR pole residues +! (Withing a Monte-Carlo performed in MG5aMC, this is automatically disabled internally) +#COLLIERComputeIRpoles +!.TRUE. +! Default :: .TRUE. + +! Decide if COLLIER must be computed multiple times to evaluate the IR pole residues +#COLLIERRequiredAccuracy +!1.0d-8 +! Default :: 1.0d-8 +! A value of -1.0d0 means that it will be automatically set from MLStabThres. +! The default value of 1.0d-8 corresponds to the value for which COLLIER's authors +! have optimized the library. + +! Decide whether to use COLLIER's internal stability test or the loop-direction +! switch test instead. +#COLLIERUseInternalStabilityTest +!.TRUE. +! Default :: .TRUE. +! COLLIER's internal stability test is at no extra cost but not as reliable +! as the loop-direction switch test, which however doubles the reduction time. +! This parameter is only relevant when running MadLoop with CTModeRun=-1. +! If you find a large number of unstable points with COLLIER for complicated +! processes, set this parameter to .FALSE. to make sure the PS points flagged +! as unstable with COLLIER really are so. + +! Set up to which N-loop to use the COLLIER global caching system. +#COLLIERGlobalCache +!-1 +! Default :: -1 +! -1 : Enable the global cache for all loops +! 0 : Disable the global cache alltogether +! N : Enable the global cache but only for up to N-loops + +! Use the global cache when evaluating the poles as well (more memory consuming) +! During a Monte-Carlo it is typically not useful anyway, because the pole +! computation is automatically disabled for COLLIER, irrespectively of the value +! of the parameters COLLIERComputepoles specified above. +#COLLIERUseCacheForPoles +!.FALSE. +! Default :: .FALSE. + +! Choose which branch(es) of COLLIER have to be used +#COLLIERMode +!1 +! Default :: 1 +! COLLIERMode=1 : COLI branch +! COLLIERMode=2 : DD branch +! COLLIERMode=3 : Both DD and COLI branch compared + +! Decide if COLLIER can output its information in a log directory. +#COLLIERCanOutput +!.FALSE. +! Default :: .FALSE. + +/* End of param file */ diff --git a/UNITTEST_proc/Cards/MadLoopParams_default.dat b/UNITTEST_proc/Cards/MadLoopParams_default.dat new file mode 100644 index 0000000000..425d909582 --- /dev/null +++ b/UNITTEST_proc/Cards/MadLoopParams_default.dat @@ -0,0 +1,298 @@ +! This file is for the user to set the different parameters of MadLoop. +! The name of the variable to define must start with the '#' sign and then +! the value should be put immediately on the next line. + +! +#MLReductionLib +!6|7|1 +! Default :: 6|7|1 +! The tensor integral reduction library.The current choices are: +! 1 | CutTools +! 2 | PJFry++ +! 3 | IREGI +! 4 | Golem95 +! 5 | Samurai +! 6 | Ninja +! 7 | COLLIER +! One can use the combinations to reduce integral,e.g. +! 1|2|3 means first use CutTools, if it is not stable, use PJFry++, +! if it is still unstable, use IREGI. If it failed, use QP of CutTools. +! Notice that any reduction tool not avaialble on the system will be automatically +! skipped. + +! When using quadruple precision with Ninja or CutTools, the reduction will +! always be done in quadruple precision, but the parameters below allow you to +! chose if you want to also recompute the *integrand* in quadruple precision. +! Doing so is slow but might improve the accuracy in some situation. +#UseQPIntegrandForCutTools +!.TRUE. +! Default :: .TRUE. +#UseQPIntegrandForNinja +!.TRUE. +! Default :: .TRUE. +! + +! ================================================================================= +! The parameters below set the parameters for IREGI +! ================================================================================= + +#IREGIMODE +!2 +! Default :: 2 +! IREGIMODE=0, IBP reduction +! IREGIMODE=1, PaVe reduction +! IREGIMODE=2, PaVe reduction with stablility improved by IBP reduction + +#IREGIRECY +!.TRUE. +! Default :: .TRUE. +! Use RECYCLING OR NOT IN IREGI +! + +! ================================================================================= +! The parameters below set the stability checks of MadLoop at run time +! ================================================================================= + +! Decide in which mode to run MadLoop +! +! imode:| description +! 1 | Double precision, loops reduced with propagator in original order +! 2 | Double precision, loops reduced with propagator with reversed order +! 4 | Quadruple precision, loops reduced with propagator in original order +! 5 | Quadruple precision, loops reduced with propagator with reversed order +! -1 | Exhaustive automated numerical stability checks. See below for details. +! +! Due to the architecture of the program, you are better off +! rerunning the full PS point in quadruple precision than just a single loop +! because the two things would almost take the same time. So '-1' is always +! very recommended. +#CTModeRun +!-1 +! Default :: -1 +! In the negative mode -1, MadLoop first evaluates each PS points in modes 1 and 2, +! yielding results Res1 and Res2, and then check if: +! (Res1-Res2)/(2*(Res1+Res2)< MLStabThres +! If it is not the case, MadLoop evaluates again the PS point in modes 4 and 5, +! yielding results Res4 and Res5, and then check if: +! (Res4-Res5)/(2*(Res4+Res5)< MLStabThres +! If it is the case then the unstable phase-space point could be cured. If it is +! not the case, MadLoop outputs a warning. +! Notice that MLStabThres is used only when CTModeRun is negative. +#MLStabThres +!1.0d-3 +! Default :: 1.0d-3 +! You can add other evaluation method to check for the stability in DP and QP. +! Below you can chose if you want to use zero, one or two rotations of the PS point +! in QP. +#NRotations_DP +!0 +! Default :: 0 +#NRotations_QP +!0 +! Default :: 0 + +! By default, MadLoop is allowed to slightly deform the Phase-Space point in input +! so to insure perfect onshellness of the external particles and perfect energy-momentum +! conservation. The deformation is minimal and such that it leaves the input PS point +! unchanged if it already satisfies the physical condiditions mentioned above. +! This integer values select what is the method to be employed preferably to restore this +! precision. It can take the following values: +! +! -1 :: No method is used for double precision computations, and method 2 will be used +! preferentially when quadruple precision (for which this precision improvement +! is mandatory, otherwise quadruple precision is pointless) +! 1 :: This methods imitates what is done in PSMC, namely +! a) Set the space-like momentum of the last external particle to be the +! opposite of the sum of the others (with a minus sign for the initial states). +! b) Rescale all final state space-like momenta by a fixed value x computed such +! that energy is conserved when particles are put exactly onshell. This value +! is determined numericaly via Ralph-Newton's method. +! c) Set all energies to have particles exactly onshell. +! 2 :: This method applies a shift to the energy and the x and y components of the first +! initial state momentum in order to restore exact energy momentum conservation after +! particles have been put exactly onshell via a shift of the z component of their +! momenta. +#ImprovePSPoint +!2 +! Default :: 2 + +! ================================================================================= +! The parameters below set two CutTools internal parameters accessible to the user. +! ================================================================================= + +! Choose here what library to chose for CutTools/TIR to compute the scalar loops of the +! master integral basis. The choices are as follows: +! (Does not apply for Golem95, where OneLOop is always used) +! 2 | OneLOop +! 3 | QCDLoop +#CTLoopLibrary +!2 +! Default :: 2 + +! Choose here the stability threshold used within CutTools to decide when to go to +! higher precision. +#CTStabThres +!1.0d-2 +! Default :: 1.0d-2 + +! ================================================================================= +! The parameters below set the general behavior of MadLoop for the initialization +! ================================================================================= + +! Decide in which mode to run when performing MadLoop's initialization of +! the helicity (and possibly loop) filter. The possible modes are: +! +! Decide in which mode to run MadLoop +! +! imode:| description +! 1 | Double precision, loops reduced with propagator in original order +! 2 | Double precision, loops reduced with propagator with reversed order +! 4 | Quadruple precision, loops reduced with propagator in original order +! 5 | Quadruple precision, loops reduced with propagator with reversed order +! +#CTModeInit +!1 +! Default :: 1 + +! CheckCycle sets on how many PS points trials the initialization filters must be +! obtained. As long as MadLoop does not find that many consecutive PS points for +! which the filters are the same, it will start over but only a maximum of +! MaxAttempts times. +#CheckCycle +!3 +! Default :: 3 +#MaxAttempts +!10 +! Default :: 10 + +! Setting the threshold for deciding wether a numerical contribution is analytically +! zero or not. +#ZeroThres +!1.0d-9 +! Default :: 1.0d-9 + +! Setting the on-shell threshold for deciding whether the invariant variables +! of external momenta are on-shell or not. It will only be used in constructing +! s-matrix in Golem95. +#OSThres +!1.0d-8 +! Default :: 1.0d-8 + +! The setting below is recommended to be on as it allows to systematically used the +! first PS point thrown at ML5 to be used for making sure that the helicity filter +! read from HelFilter.dat is consistent as it might be no longer up to date with +! certain changes of the paramaters by the user. +#DoubleCheckHelicityFilter +!.TRUE. +! Default :: .TRUE. + +! This decides whether to write out the helicity and loop filters to the files +! HelFilters.dat and LoopFilters.dat to save them for future runs. It usually +! preferable but sometimes not desired because of the need of threadlocks in the +! context of mpi parallelization. So it can be turned off here in such cases. +#WriteOutFilters +!.TRUE. +! Default :: .TRUE. + +! Some loop contributions may be zero for some helicities which are however +! contributing. In order to save their computing time, you can chose here to try +! to filter them out. The gain is typically minimal, so it is turned off by default. +#UseLoopFilter +!.FALSE. +! Default :: .FALSE. + +! The integer below set at which level the user wants to filter helicity configuration. +! Notice that this does not entail any approximation. It only offers the possibility of +! performing exact simplifications based on numerical checks. HelicityFilterLevel = +! 0 : No filtering at all. Not HelFilter.dat file will be written out and *all* helicity +! configurations will be computed. +! 1 : Analytically zero helicity configurations will be recognized as such by numerical +! comparisons (using the 'ZeroThres' param) and consistently skipped in further +! computations. +! 2 : Filters both helicity configuration which are analytically zero *and* those +! consistently identical (typically because of CP symmetry). +! (Will only effectively do it if process was generated in 'optimized_mode') +#HelicityFilterLevel +!2 +! Default :: 2 + +! This decides whether consecutive consistency for the loop filtering setup is also +! required. +#LoopInitStartOver +!.FALSE. +! Default :: .FALSE. + +! This decides wether consecutive consistency for the helicity filtering setup is also +! required. Better to set it to false as it can cause problems for unstable processes. +#HelInitStartOver +!.FALSE. +! Default :: .FALSE. + +! ================================================================================= +! The parameters below set the main parameters for COLLIER +! To edit more specific technical COLLIER parameters, modify directly the content +! of the subroutine 'INITCOLLIER' in the file 'MadLoopCommons.f' +! ================================================================================= + +! Decide if COLLIER must be computed multiple times to evaluate the UV pole residues +! (Withing a Monte-Carlo performed in MG5aMC, this is automatically disabled internally) +#COLLIERComputeUVpoles +!.TRUE. +! Default :: .TRUE. + +! Decide if COLLIER must be computed multiple times to evaluate the IR pole residues +! (Withing a Monte-Carlo performed in MG5aMC, this is automatically disabled internally) +#COLLIERComputeIRpoles +!.TRUE. +! Default :: .TRUE. + +! Decide if COLLIER must be computed multiple times to evaluate the IR pole residues +#COLLIERRequiredAccuracy +!1.0d-8 +! Default :: 1.0d-8 +! A value of -1.0d0 means that it will be automatically set from MLStabThres. +! The default value of 1.0d-8 corresponds to the value for which COLLIER's authors +! have optimized the library. + +! Decide whether to use COLLIER's internal stability test or the loop-direction +! switch test instead. +#COLLIERUseInternalStabilityTest +!.TRUE. +! Default :: .TRUE. +! COLLIER's internal stability test is at no extra cost but not as reliable +! as the loop-direction switch test, which however doubles the reduction time. +! This parameter is only relevant when running MadLoop with CTModeRun=-1. +! If you find a large number of unstable points with COLLIER for complicated +! processes, set this parameter to .FALSE. to make sure the PS points flagged +! as unstable with COLLIER really are so. + +! Set up to which N-loop to use the COLLIER global caching system. +#COLLIERGlobalCache +!-1 +! Default :: -1 +! -1 : Enable the global cache for all loops +! 0 : Disable the global cache alltogether +! N : Enable the global cache but only for up to N-loops + +! Use the global cache when evaluating the poles as well (more memory consuming) +! During a Monte-Carlo it is typically not useful anyway, because the pole +! computation is automatically disabled for COLLIER, irrespectively of the value +! of the parameters COLLIERComputepoles specified above. +#COLLIERUseCacheForPoles +!.FALSE. +! Default :: .FALSE. + +! Choose which branch(es) of COLLIER have to be used +#COLLIERMode +!1 +! Default :: 1 +! COLLIERMode=1 : COLI branch +! COLLIERMode=2 : DD branch +! COLLIERMode=3 : Both DD and COLI branch compared + +! Decide if COLLIER can output its information in a log directory. +#COLLIERCanOutput +!.FALSE. +! Default :: .FALSE. + +/* End of param file */ diff --git a/UNITTEST_proc/Cards/ident_card.dat b/UNITTEST_proc/Cards/ident_card.dat new file mode 100644 index 0000000000..debdfc8611 --- /dev/null +++ b/UNITTEST_proc/Cards/ident_card.dat @@ -0,0 +1,35 @@ +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +c written by the UFO converter +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc + +loop 1 MU_R + +sminputs 1 aEWM1 + +sminputs 2 mdl_Gf + +sminputs 3 aS + +yukawa 5 mdl_ymb + +yukawa 6 mdl_ymt + +yukawa 15 mdl_ymtau + +mass 6 mdl_MT + +mass 5 mdl_MB + +mass 23 mdl_MZ + +mass 25 mdl_MH + +mass 15 mdl_MTA + +decay 6 mdl_WT + +decay 23 mdl_WZ + +decay 24 mdl_WW + +decay 25 mdl_WH diff --git a/UNITTEST_proc/Cards/param_card.dat b/UNITTEST_proc/Cards/param_card.dat new file mode 100644 index 0000000000..faa7fa5274 --- /dev/null +++ b/UNITTEST_proc/Cards/param_card.dat @@ -0,0 +1,93 @@ +###################################################################### +## PARAM_CARD AUTOMATICALLY GENERATED BY MG5 FOLLOWING UFO MODEL #### +###################################################################### +## ## +## Width set on Auto will be computed following the information ## +## present in the decay.py files of the model. ## +## See arXiv:1402.1178 for more details. ## +## ## +###################################################################### + +################################### +## INFORMATION FOR LOOP +################################### +Block loop + 1 9.118800e+01 # MU_R + +################################### +## INFORMATION FOR MASS +################################### +Block mass + 5 4.700000e+00 # MB + 6 1.730000e+02 # MT + 15 1.777000e+00 # MTA + 23 9.118800e+01 # MZ + 25 1.250000e+02 # MH +## Dependent parameters, given by model restrictions. +## Those values should be edited following the +## analytical expression. MG5 ignores those values +## but they are important for interfacing the output of MG5 +## to external program such as Pythia. + 1 0.000000e+00 # d : 0.0 + 2 0.000000e+00 # u : 0.0 + 3 0.000000e+00 # s : 0.0 + 4 0.000000e+00 # c : 0.0 + 11 0.000000e+00 # e- : 0.0 + 12 0.000000e+00 # ve : 0.0 + 13 0.000000e+00 # m- : 0.0 + 14 0.000000e+00 # vm : 0.0 + 16 0.000000e+00 # vt : 0.0 + 21 0.000000e+00 # g : 0.0 + 22 0.000000e+00 # a : 0.0 + 24 8.041900e+01 # w+ : cmath.sqrt(MZ__exp__2/2. + cmath.sqrt(MZ__exp__4/4. - (aEW*cmath.pi*MZ__exp__2)/(Gf*sqrt__2))) + +################################### +## INFORMATION FOR SMINPUTS +################################### +Block sminputs + 1 1.325070e+02 # aEWM1 + 2 1.166390e-05 # Gf + 3 1.180000e-01 # aS (Note: this Parameter is not used if you use a PDF set) + +################################### +## INFORMATION FOR YUKAWA +################################### +Block yukawa + 5 4.700000e+00 # ymb + 6 1.730000e+02 # ymt + 15 1.777000e+00 # ymtau + +################################### +## INFORMATION FOR DECAY +################################### +DECAY 6 1.491500e+00 # WT +DECAY 23 2.441404e+00 # WZ +DECAY 24 2.047600e+00 # WW +DECAY 25 6.382339e-03 # WH +## Dependent parameters, given by model restrictions. +## Those values should be edited following the +## analytical expression. MG5 ignores those values +## but they are important for interfacing the output of MG5 +## to external program such as Pythia. +DECAY 1 0.000000e+00 # d : 0.0 +DECAY 2 0.000000e+00 # u : 0.0 +DECAY 3 0.000000e+00 # s : 0.0 +DECAY 4 0.000000e+00 # c : 0.0 +DECAY 5 0.000000e+00 # b : 0.0 +DECAY 11 0.000000e+00 # e- : 0.0 +DECAY 12 0.000000e+00 # ve : 0.0 +DECAY 13 0.000000e+00 # m- : 0.0 +DECAY 14 0.000000e+00 # vm : 0.0 +DECAY 15 0.000000e+00 # tt- : 0.0 +DECAY 16 0.000000e+00 # vt : 0.0 +DECAY 21 0.000000e+00 # g : 0.0 +DECAY 22 0.000000e+00 # a : 0.0 +#=========================================================== +# QUANTUM NUMBERS OF NEW STATE(S) (NON SM PDG CODE) +#=========================================================== + +Block QNUMBERS 82 # gh + 1 0 # 3 times electric charge + 2 1 # number of spin states (2S+1) + 3 8 # colour rep (1: singlet, 3: triplet, 8: octet) + 4 1 # Particle/Antiparticle distinction (0=own anti) diff --git a/UNITTEST_proc/Cards/param_card_default.dat b/UNITTEST_proc/Cards/param_card_default.dat new file mode 100644 index 0000000000..faa7fa5274 --- /dev/null +++ b/UNITTEST_proc/Cards/param_card_default.dat @@ -0,0 +1,93 @@ +###################################################################### +## PARAM_CARD AUTOMATICALLY GENERATED BY MG5 FOLLOWING UFO MODEL #### +###################################################################### +## ## +## Width set on Auto will be computed following the information ## +## present in the decay.py files of the model. ## +## See arXiv:1402.1178 for more details. ## +## ## +###################################################################### + +################################### +## INFORMATION FOR LOOP +################################### +Block loop + 1 9.118800e+01 # MU_R + +################################### +## INFORMATION FOR MASS +################################### +Block mass + 5 4.700000e+00 # MB + 6 1.730000e+02 # MT + 15 1.777000e+00 # MTA + 23 9.118800e+01 # MZ + 25 1.250000e+02 # MH +## Dependent parameters, given by model restrictions. +## Those values should be edited following the +## analytical expression. MG5 ignores those values +## but they are important for interfacing the output of MG5 +## to external program such as Pythia. + 1 0.000000e+00 # d : 0.0 + 2 0.000000e+00 # u : 0.0 + 3 0.000000e+00 # s : 0.0 + 4 0.000000e+00 # c : 0.0 + 11 0.000000e+00 # e- : 0.0 + 12 0.000000e+00 # ve : 0.0 + 13 0.000000e+00 # m- : 0.0 + 14 0.000000e+00 # vm : 0.0 + 16 0.000000e+00 # vt : 0.0 + 21 0.000000e+00 # g : 0.0 + 22 0.000000e+00 # a : 0.0 + 24 8.041900e+01 # w+ : cmath.sqrt(MZ__exp__2/2. + cmath.sqrt(MZ__exp__4/4. - (aEW*cmath.pi*MZ__exp__2)/(Gf*sqrt__2))) + +################################### +## INFORMATION FOR SMINPUTS +################################### +Block sminputs + 1 1.325070e+02 # aEWM1 + 2 1.166390e-05 # Gf + 3 1.180000e-01 # aS (Note: this Parameter is not used if you use a PDF set) + +################################### +## INFORMATION FOR YUKAWA +################################### +Block yukawa + 5 4.700000e+00 # ymb + 6 1.730000e+02 # ymt + 15 1.777000e+00 # ymtau + +################################### +## INFORMATION FOR DECAY +################################### +DECAY 6 1.491500e+00 # WT +DECAY 23 2.441404e+00 # WZ +DECAY 24 2.047600e+00 # WW +DECAY 25 6.382339e-03 # WH +## Dependent parameters, given by model restrictions. +## Those values should be edited following the +## analytical expression. MG5 ignores those values +## but they are important for interfacing the output of MG5 +## to external program such as Pythia. +DECAY 1 0.000000e+00 # d : 0.0 +DECAY 2 0.000000e+00 # u : 0.0 +DECAY 3 0.000000e+00 # s : 0.0 +DECAY 4 0.000000e+00 # c : 0.0 +DECAY 5 0.000000e+00 # b : 0.0 +DECAY 11 0.000000e+00 # e- : 0.0 +DECAY 12 0.000000e+00 # ve : 0.0 +DECAY 13 0.000000e+00 # m- : 0.0 +DECAY 14 0.000000e+00 # vm : 0.0 +DECAY 15 0.000000e+00 # tt- : 0.0 +DECAY 16 0.000000e+00 # vt : 0.0 +DECAY 21 0.000000e+00 # g : 0.0 +DECAY 22 0.000000e+00 # a : 0.0 +#=========================================================== +# QUANTUM NUMBERS OF NEW STATE(S) (NON SM PDG CODE) +#=========================================================== + +Block QNUMBERS 82 # gh + 1 0 # 3 times electric charge + 2 1 # number of spin states (2S+1) + 3 8 # colour rep (1: singlet, 3: triplet, 8: octet) + 4 1 # Particle/Antiparticle distinction (0=own anti) diff --git a/UNITTEST_proc/MGMEVersion.txt b/UNITTEST_proc/MGMEVersion.txt new file mode 100644 index 0000000000..0281a4e427 --- /dev/null +++ b/UNITTEST_proc/MGMEVersion.txt @@ -0,0 +1 @@ +5.3.7.2 \ No newline at end of file diff --git a/UNITTEST_proc/Source/DHELAS/FFV1LP0_3.f b/UNITTEST_proc/Source/DHELAS/FFV1LP0_3.f new file mode 100644 index 0000000000..a03d6ab4a1 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/FFV1LP0_3.f @@ -0,0 +1,29 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C Gamma(3,2,1) +C + SUBROUTINE FFV1LP0_3(F1, F2, COUP, M3, W3,V3) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*16 CI + PARAMETER (CI=(0D0,1D0)) + COMPLEX*16 COUP + TYPE(ALOHA) F1 + INTEGER FLV_INDEX1 + TYPE(ALOHA) F2 + INTEGER FLV_INDEX2 + REAL*8 M3 + TYPE(ALOHA) V3 + REAL*8 W3 + V3%P(:) = +F1%P(:)+F2%P(:) + V3%W(1)= COUP*(-CI)*(F2 % W(3)*F1 % W(1)+F2 % W(4)*F1 % W(2)+F2 + $ % W(1)*F1 % W(3)+F2 % W(2)*F1 % W(4)) + V3%W(2)= COUP*(-CI)*(-F2 % W(4)*F1 % W(1)-F2 % W(3)*F1 % W(2)+F2 + $ % W(2)*F1 % W(3)+F2 % W(1)*F1 % W(4)) + V3%W(3)= COUP*(-CI)*(-CI*(F2 % W(4)*F1 % W(1)+F2 % W(1)*F1 % W(4) + $ )+CI*(F2 % W(3)*F1 % W(2)+F2 % W(2)*F1 % W(3))) + V3%W(4)= COUP*(-CI)*(-F2 % W(3)*F1 % W(1)-F2 % W(2)*F1 % W(4)+F2 + $ % W(4)*F1 % W(2)+F2 % W(1)*F1 % W(3)) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/FFV1L_1.f b/UNITTEST_proc/Source/DHELAS/FFV1L_1.f new file mode 100644 index 0000000000..6a648b7657 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/FFV1L_1.f @@ -0,0 +1,51 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C Gamma(3,2,1) +C + SUBROUTINE FFV1L_1(F2, V3, COUP, M1, W1,F1) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*16 CI + PARAMETER (CI=(0D0,1D0)) + COMPLEX*16 COUP + TYPE(ALOHA) F1 + INTEGER FLV_INDEX1 + TYPE(ALOHA) F2 + INTEGER FLV_INDEX2 + REAL*8 M1 + COMPLEX*16 P1(0:3) + TYPE(ALOHA) V3 + REAL*8 W1 + F1%P(:) = +F2%P(:)+V3%P(:) + P1(:) = -F1 % P (:) + F1%W(1)= COUP*CI*(F2 % W(1)*(P1(0)*(-V3 % W(1)+V3 % W(4))+(P1(1) + $ *(V3 % W(2)-CI*(V3 % W(3)))+(P1(2)*(+CI*(V3 % W(2))+V3 % W(3)) + $ +P1(3)*(-V3 % W(1)+V3 % W(4)))))+(F2 % W(2)*(P1(0)*(V3 % W(2) + $ +CI*(V3 % W(3)))+(P1(1)*(-1D0)*(V3 % W(1)+V3 % W(4))+(P1(2)*( + $ -1D0)*(+CI*(V3 % W(1)+V3 % W(4)))+P1(3)*(V3 % W(2)+CI*(V3 % W(3) + $ )))))+M1*(F2 % W(3)*(V3 % W(1)+V3 % W(4))+F2 % W(4)*(V3 % W(2) + $ +CI*(V3 % W(3)))))) + F1%W(2)= COUP*(-CI)*(F2 % W(1)*(P1(0)*(-V3 % W(2)+CI*(V3 % W(3))) + $ +(P1(1)*(V3 % W(1)-V3 % W(4))+(P1(2)*(-CI*(V3 % W(1))+CI*(V3 % + $ W(4)))+P1(3)*(V3 % W(2)-CI*(V3 % W(3))))))+(F2 % W(2)*(P1(0) + $ *(V3 % W(1)+V3 % W(4))+(P1(1)*(-1D0)*(V3 % W(2)+CI*(V3 % W(3))) + $ +(P1(2)*(+CI*(V3 % W(2))-V3 % W(3))-P1(3)*(V3 % W(1)+V3 % W(4))) + $ ))+M1*(F2 % W(3)*(-V3 % W(2)+CI*(V3 % W(3)))+F2 % W(4)*(-V3 % + $ W(1)+V3 % W(4))))) + F1%W(3)= COUP*(-CI)*(F2 % W(3)*(P1(0)*(V3 % W(1)+V3 % W(4)) + $ +(P1(1)*(-V3 % W(2)+CI*(V3 % W(3)))+(P1(2)*(-1D0)*(+CI*(V3 % + $ W(2))+V3 % W(3))-P1(3)*(V3 % W(1)+V3 % W(4)))))+(F2 % W(4) + $ *(P1(0)*(V3 % W(2)+CI*(V3 % W(3)))+(P1(1)*(-V3 % W(1)+V3 % W(4)) + $ +(P1(2)*(-CI*(V3 % W(1))+CI*(V3 % W(4)))-P1(3)*(V3 % W(2)+CI + $ *(V3 % W(3))))))+M1*(F2 % W(1)*(-V3 % W(1)+V3 % W(4))+F2 % W(2) + $ *(V3 % W(2)+CI*(V3 % W(3)))))) + F1%W(4)= COUP*CI*(F2 % W(3)*(P1(0)*(-V3 % W(2)+CI*(V3 % W(3))) + $ +(P1(1)*(V3 % W(1)+V3 % W(4))+(P1(2)*(-1D0)*(+CI*(V3 % W(1)+V3 + $ % W(4)))+P1(3)*(-V3 % W(2)+CI*(V3 % W(3))))))+(F2 % W(4)*(P1(0) + $ *(-V3 % W(1)+V3 % W(4))+(P1(1)*(V3 % W(2)+CI*(V3 % W(3)))+(P1(2) + $ *(-CI*(V3 % W(2))+V3 % W(3))+P1(3)*(-V3 % W(1)+V3 % W(4)))))+M1 + $ *(F2 % W(1)*(-V3 % W(2)+CI*(V3 % W(3)))+F2 % W(2)*(V3 % W(1)+V3 + $ % W(4))))) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/FFV1L_2.f b/UNITTEST_proc/Source/DHELAS/FFV1L_2.f new file mode 100644 index 0000000000..5df2242794 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/FFV1L_2.f @@ -0,0 +1,51 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C Gamma(3,2,1) +C + SUBROUTINE FFV1L_2(F1, V3, COUP, M2, W2,F2) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*16 CI + PARAMETER (CI=(0D0,1D0)) + COMPLEX*16 COUP + TYPE(ALOHA) F1 + INTEGER FLV_INDEX1 + TYPE(ALOHA) F2 + INTEGER FLV_INDEX2 + REAL*8 M2 + COMPLEX*16 P2(0:3) + TYPE(ALOHA) V3 + REAL*8 W2 + F2%P(:) = +F1%P(:)+V3%P(:) + P2(:) = -F2 % P (:) + F2%W(1)= COUP*CI*(F1 % W(1)*(P2(0)*(V3 % W(1)+V3 % W(4))+(P2(1) + $ *(-1D0)*(V3 % W(2)+CI*(V3 % W(3)))+(P2(2)*(+CI*(V3 % W(2))-V3 % + $ W(3))-P2(3)*(V3 % W(1)+V3 % W(4)))))+(F1 % W(2)*(P2(0)*(V3 % + $ W(2)-CI*(V3 % W(3)))+(P2(1)*(-V3 % W(1)+V3 % W(4))+(P2(2)*(+CI + $ *(V3 % W(1))-CI*(V3 % W(4)))+P2(3)*(-V3 % W(2)+CI*(V3 % W(3))))) + $ )+M2*(F1 % W(3)*(V3 % W(1)-V3 % W(4))+F1 % W(4)*(-V3 % W(2)+CI + $ *(V3 % W(3)))))) + F2%W(2)= COUP*(-CI)*(F1 % W(1)*(P2(0)*(-1D0)*(V3 % W(2)+CI*(V3 % + $ W(3)))+(P2(1)*(V3 % W(1)+V3 % W(4))+(P2(2)*(+CI*(V3 % W(1)+V3 + $ % W(4)))-P2(3)*(V3 % W(2)+CI*(V3 % W(3))))))+(F1 % W(2)*(P2(0) + $ *(-V3 % W(1)+V3 % W(4))+(P2(1)*(V3 % W(2)-CI*(V3 % W(3)))+(P2(2) + $ *(+CI*(V3 % W(2))+V3 % W(3))+P2(3)*(-V3 % W(1)+V3 % W(4)))))+M2 + $ *(F1 % W(3)*(V3 % W(2)+CI*(V3 % W(3)))-F1 % W(4)*(V3 % W(1)+V3 + $ % W(4))))) + F2%W(3)= COUP*(-CI)*(F1 % W(3)*(P2(0)*(-V3 % W(1)+V3 % W(4)) + $ +(P2(1)*(V3 % W(2)+CI*(V3 % W(3)))+(P2(2)*(-CI*(V3 % W(2))+V3 % + $ W(3))+P2(3)*(-V3 % W(1)+V3 % W(4)))))+(F1 % W(4)*(P2(0)*(V3 % + $ W(2)-CI*(V3 % W(3)))+(P2(1)*(-1D0)*(V3 % W(1)+V3 % W(4))+(P2(2) + $ *(+CI*(V3 % W(1)+V3 % W(4)))+P2(3)*(V3 % W(2)-CI*(V3 % W(3)))))) + $ +M2*(F1 % W(1)*(-1D0)*(V3 % W(1)+V3 % W(4))+F1 % W(2)*(-V3 % + $ W(2)+CI*(V3 % W(3)))))) + F2%W(4)= COUP*CI*(F1 % W(3)*(P2(0)*(-1D0)*(V3 % W(2)+CI*(V3 % + $ W(3)))+(P2(1)*(V3 % W(1)-V3 % W(4))+(P2(2)*(+CI*(V3 % W(1))-CI + $ *(V3 % W(4)))+P2(3)*(V3 % W(2)+CI*(V3 % W(3))))))+(F1 % W(4) + $ *(P2(0)*(V3 % W(1)+V3 % W(4))+(P2(1)*(-V3 % W(2)+CI*(V3 % W(3))) + $ +(P2(2)*(-1D0)*(+CI*(V3 % W(2))+V3 % W(3))-P2(3)*(V3 % W(1)+V3 + $ % W(4)))))+M2*(F1 % W(1)*(V3 % W(2)+CI*(V3 % W(3)))+F1 % W(2) + $ *(V3 % W(1)-V3 % W(4))))) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/FFV1P0_3.f b/UNITTEST_proc/Source/DHELAS/FFV1P0_3.f new file mode 100644 index 0000000000..e537fbd97f --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/FFV1P0_3.f @@ -0,0 +1,40 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C Gamma(3,2,1) +C + SUBROUTINE FFV1P0_3(F1, F2, COUP, M3, W3,V3) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*16 CI + PARAMETER (CI=(0D0,1D0)) + COMPLEX*16 COUP + TYPE(ALOHA) F1 + INTEGER FLV_INDEX1 + TYPE(ALOHA) F2 + INTEGER FLV_INDEX2 + REAL*8 M3 + REAL*8 P3(0:3) + TYPE(ALOHA) V3 + REAL*8 W3 + COMPLEX*16 DENOM + V3%P(:) = +F1%P(:)+F2%P(:) + P3(:) = -V3 % P (:) + FLV_INDEX1 = F1 %FLV_INDEX + FLV_INDEX2 = F2 %FLV_INDEX + IF(FLV_INDEX1.NE.FLV_INDEX2.OR.FLV_INDEX1.EQ.0)THEN + V3%W(:) = (0D0,0D0) + RETURN + ENDIF + DENOM = COUP/(P3(0)**2-P3(1)**2-P3(2)**2-P3(3)**2 - M3 * (M3 -CI + $ * W3)) + V3%W(1)= DENOM*(-CI)*(F2 % W(3)*F1 % W(1)+F2 % W(4)*F1 % W(2)+F2 + $ % W(1)*F1 % W(3)+F2 % W(2)*F1 % W(4)) + V3%W(2)= DENOM*(-CI)*(-F2 % W(4)*F1 % W(1)-F2 % W(3)*F1 % W(2) + $ +F2 % W(2)*F1 % W(3)+F2 % W(1)*F1 % W(4)) + V3%W(3)= DENOM*(-CI)*(-CI*(F2 % W(4)*F1 % W(1)+F2 % W(1)*F1 % + $ W(4))+CI*(F2 % W(3)*F1 % W(2)+F2 % W(2)*F1 % W(3))) + V3%W(4)= DENOM*(-CI)*(-F2 % W(3)*F1 % W(1)-F2 % W(2)*F1 % W(4) + $ +F2 % W(4)*F1 % W(2)+F2 % W(1)*F1 % W(3)) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/FFV1_0.f b/UNITTEST_proc/Source/DHELAS/FFV1_0.f new file mode 100644 index 0000000000..a2f6d26199 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/FFV1_0.f @@ -0,0 +1,33 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C Gamma(3,2,1) +C + SUBROUTINE FFV1_0(F1, F2, V3, COUP,VERTEX) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*16 CI + PARAMETER (CI=(0D0,1D0)) + COMPLEX*16 COUP + TYPE(ALOHA) F1 + INTEGER FLV_INDEX1 + TYPE(ALOHA) F2 + INTEGER FLV_INDEX2 + COMPLEX*16 TMP10 + TYPE(ALOHA) V3 + COMPLEX*16 VERTEX + FLV_INDEX1 = F1 %FLV_INDEX + FLV_INDEX2 = F2 %FLV_INDEX + IF(FLV_INDEX1.NE.FLV_INDEX2.OR.FLV_INDEX1.EQ.0)THEN + VERTEX = (0D0,0D0) + RETURN + ENDIF + TMP10 = (F1 % W(1)*(F2 % W(3)*(V3 % W(1)+V3 % W(4))+F2 % W(4) + $ *(V3 % W(2)+CI*(V3 % W(3))))+(F1 % W(2)*(F2 % W(3)*(V3 % W(2) + $ -CI*(V3 % W(3)))+F2 % W(4)*(V3 % W(1)-V3 % W(4)))+(F1 % W(3) + $ *(F2 % W(1)*(V3 % W(1)-V3 % W(4))-F2 % W(2)*(V3 % W(2)+CI*(V3 % + $ W(3))))+F1 % W(4)*(F2 % W(1)*(-V3 % W(2)+CI*(V3 % W(3)))+F2 % + $ W(2)*(V3 % W(1)+V3 % W(4)))))) + VERTEX = COUP*(-CI * TMP10) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/FFV1_1.f b/UNITTEST_proc/Source/DHELAS/FFV1_1.f new file mode 100644 index 0000000000..d61c39598c --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/FFV1_1.f @@ -0,0 +1,55 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C Gamma(3,2,1) +C + SUBROUTINE FFV1_1(F2, V3, COUP, M1, W1,F1) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*16 CI + PARAMETER (CI=(0D0,1D0)) + COMPLEX*16 COUP + TYPE(ALOHA) F1 + INTEGER FLV_INDEX1 + TYPE(ALOHA) F2 + INTEGER FLV_INDEX2 + REAL*8 M1 + REAL*8 P1(0:3) + TYPE(ALOHA) V3 + REAL*8 W1 + COMPLEX*16 DENOM + F1%P(:) = +F2%P(:)+V3%P(:) + P1(:) = -F1 % P (:) + F1 % FLV_INDEX = F2 % FLV_INDEX + DENOM = COUP/(P1(0)**2-P1(1)**2-P1(2)**2-P1(3)**2 - M1 * (M1 -CI + $ * W1)) + F1%W(1)= DENOM*CI*(F2 % W(1)*(P1(0)*(-V3 % W(1)+V3 % W(4))+(P1(1) + $ *(V3 % W(2)-CI*(V3 % W(3)))+(P1(2)*(+CI*(V3 % W(2))+V3 % W(3)) + $ +P1(3)*(-V3 % W(1)+V3 % W(4)))))+(F2 % W(2)*(P1(0)*(V3 % W(2) + $ +CI*(V3 % W(3)))+(P1(1)*(-1D0)*(V3 % W(1)+V3 % W(4))+(P1(2)*( + $ -1D0)*(+CI*(V3 % W(1)+V3 % W(4)))+P1(3)*(V3 % W(2)+CI*(V3 % W(3) + $ )))))+M1*(F2 % W(3)*(V3 % W(1)+V3 % W(4))+F2 % W(4)*(V3 % W(2) + $ +CI*(V3 % W(3)))))) + F1%W(2)= DENOM*(-CI)*(F2 % W(1)*(P1(0)*(-V3 % W(2)+CI*(V3 % W(3)) + $ )+(P1(1)*(V3 % W(1)-V3 % W(4))+(P1(2)*(-CI*(V3 % W(1))+CI*(V3 % + $ W(4)))+P1(3)*(V3 % W(2)-CI*(V3 % W(3))))))+(F2 % W(2)*(P1(0) + $ *(V3 % W(1)+V3 % W(4))+(P1(1)*(-1D0)*(V3 % W(2)+CI*(V3 % W(3))) + $ +(P1(2)*(+CI*(V3 % W(2))-V3 % W(3))-P1(3)*(V3 % W(1)+V3 % W(4))) + $ ))+M1*(F2 % W(3)*(-V3 % W(2)+CI*(V3 % W(3)))+F2 % W(4)*(-V3 % + $ W(1)+V3 % W(4))))) + F1%W(3)= DENOM*(-CI)*(F2 % W(3)*(P1(0)*(V3 % W(1)+V3 % W(4)) + $ +(P1(1)*(-V3 % W(2)+CI*(V3 % W(3)))+(P1(2)*(-1D0)*(+CI*(V3 % + $ W(2))+V3 % W(3))-P1(3)*(V3 % W(1)+V3 % W(4)))))+(F2 % W(4) + $ *(P1(0)*(V3 % W(2)+CI*(V3 % W(3)))+(P1(1)*(-V3 % W(1)+V3 % W(4)) + $ +(P1(2)*(-CI*(V3 % W(1))+CI*(V3 % W(4)))-P1(3)*(V3 % W(2)+CI + $ *(V3 % W(3))))))+M1*(F2 % W(1)*(-V3 % W(1)+V3 % W(4))+F2 % W(2) + $ *(V3 % W(2)+CI*(V3 % W(3)))))) + F1%W(4)= DENOM*CI*(F2 % W(3)*(P1(0)*(-V3 % W(2)+CI*(V3 % W(3))) + $ +(P1(1)*(V3 % W(1)+V3 % W(4))+(P1(2)*(-1D0)*(+CI*(V3 % W(1)+V3 + $ % W(4)))+P1(3)*(-V3 % W(2)+CI*(V3 % W(3))))))+(F2 % W(4)*(P1(0) + $ *(-V3 % W(1)+V3 % W(4))+(P1(1)*(V3 % W(2)+CI*(V3 % W(3)))+(P1(2) + $ *(-CI*(V3 % W(2))+V3 % W(3))+P1(3)*(-V3 % W(1)+V3 % W(4)))))+M1 + $ *(F2 % W(1)*(-V3 % W(2)+CI*(V3 % W(3)))+F2 % W(2)*(V3 % W(1)+V3 + $ % W(4))))) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/FFV1_2.f b/UNITTEST_proc/Source/DHELAS/FFV1_2.f new file mode 100644 index 0000000000..0227b562f7 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/FFV1_2.f @@ -0,0 +1,55 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C Gamma(3,2,1) +C + SUBROUTINE FFV1_2(F1, V3, COUP, M2, W2,F2) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*16 CI + PARAMETER (CI=(0D0,1D0)) + COMPLEX*16 COUP + TYPE(ALOHA) F1 + INTEGER FLV_INDEX1 + TYPE(ALOHA) F2 + INTEGER FLV_INDEX2 + REAL*8 M2 + REAL*8 P2(0:3) + TYPE(ALOHA) V3 + REAL*8 W2 + COMPLEX*16 DENOM + F2%P(:) = +F1%P(:)+V3%P(:) + P2(:) = -F2 % P (:) + F2 % FLV_INDEX = F1 % FLV_INDEX + DENOM = COUP/(P2(0)**2-P2(1)**2-P2(2)**2-P2(3)**2 - M2 * (M2 -CI + $ * W2)) + F2%W(1)= DENOM*CI*(F1 % W(1)*(P2(0)*(V3 % W(1)+V3 % W(4))+(P2(1) + $ *(-1D0)*(V3 % W(2)+CI*(V3 % W(3)))+(P2(2)*(+CI*(V3 % W(2))-V3 % + $ W(3))-P2(3)*(V3 % W(1)+V3 % W(4)))))+(F1 % W(2)*(P2(0)*(V3 % + $ W(2)-CI*(V3 % W(3)))+(P2(1)*(-V3 % W(1)+V3 % W(4))+(P2(2)*(+CI + $ *(V3 % W(1))-CI*(V3 % W(4)))+P2(3)*(-V3 % W(2)+CI*(V3 % W(3))))) + $ )+M2*(F1 % W(3)*(V3 % W(1)-V3 % W(4))+F1 % W(4)*(-V3 % W(2)+CI + $ *(V3 % W(3)))))) + F2%W(2)= DENOM*(-CI)*(F1 % W(1)*(P2(0)*(-1D0)*(V3 % W(2)+CI*(V3 + $ % W(3)))+(P2(1)*(V3 % W(1)+V3 % W(4))+(P2(2)*(+CI*(V3 % W(1) + $ +V3 % W(4)))-P2(3)*(V3 % W(2)+CI*(V3 % W(3))))))+(F1 % W(2) + $ *(P2(0)*(-V3 % W(1)+V3 % W(4))+(P2(1)*(V3 % W(2)-CI*(V3 % W(3))) + $ +(P2(2)*(+CI*(V3 % W(2))+V3 % W(3))+P2(3)*(-V3 % W(1)+V3 % W(4)) + $ )))+M2*(F1 % W(3)*(V3 % W(2)+CI*(V3 % W(3)))-F1 % W(4)*(V3 % + $ W(1)+V3 % W(4))))) + F2%W(3)= DENOM*(-CI)*(F1 % W(3)*(P2(0)*(-V3 % W(1)+V3 % W(4)) + $ +(P2(1)*(V3 % W(2)+CI*(V3 % W(3)))+(P2(2)*(-CI*(V3 % W(2))+V3 % + $ W(3))+P2(3)*(-V3 % W(1)+V3 % W(4)))))+(F1 % W(4)*(P2(0)*(V3 % + $ W(2)-CI*(V3 % W(3)))+(P2(1)*(-1D0)*(V3 % W(1)+V3 % W(4))+(P2(2) + $ *(+CI*(V3 % W(1)+V3 % W(4)))+P2(3)*(V3 % W(2)-CI*(V3 % W(3)))))) + $ +M2*(F1 % W(1)*(-1D0)*(V3 % W(1)+V3 % W(4))+F1 % W(2)*(-V3 % + $ W(2)+CI*(V3 % W(3)))))) + F2%W(4)= DENOM*CI*(F1 % W(3)*(P2(0)*(-1D0)*(V3 % W(2)+CI*(V3 % + $ W(3)))+(P2(1)*(V3 % W(1)-V3 % W(4))+(P2(2)*(+CI*(V3 % W(1))-CI + $ *(V3 % W(4)))+P2(3)*(V3 % W(2)+CI*(V3 % W(3))))))+(F1 % W(4) + $ *(P2(0)*(V3 % W(1)+V3 % W(4))+(P2(1)*(-V3 % W(2)+CI*(V3 % W(3))) + $ +(P2(2)*(-1D0)*(+CI*(V3 % W(2))+V3 % W(3))-P2(3)*(V3 % W(1)+V3 + $ % W(4)))))+M2*(F1 % W(1)*(V3 % W(2)+CI*(V3 % W(3)))+F1 % W(2) + $ *(V3 % W(1)-V3 % W(4))))) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/GHGHGL_1.f b/UNITTEST_proc/Source/DHELAS/GHGHGL_1.f new file mode 100644 index 0000000000..fec8618ce7 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/GHGHGL_1.f @@ -0,0 +1,25 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C P(3,2) +C + SUBROUTINE GHGHGL_1(S2, V3, COUP, M1, W1,S1) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*16 CI + PARAMETER (CI=(0D0,1D0)) + COMPLEX*16 COUP + REAL*8 M1 + COMPLEX*16 P2(0:3) + TYPE(ALOHA) S1 + TYPE(ALOHA) S2 + COMPLEX*16 TMP1 + TYPE(ALOHA) V3 + REAL*8 W1 + P2(:) = S2 % P (:) + S1%P(:) = +S2%P(:)+V3%P(:) + TMP1 = (V3 % W(1)*P2(0)-V3 % W(2)*P2(1)-V3 % W(3)*P2(2)-V3 % W(4) + $ *P2(3)) + S1%W(1)= COUP*CI * TMP1*S2 % W(1) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/GHGHGL_2.f b/UNITTEST_proc/Source/DHELAS/GHGHGL_2.f new file mode 100644 index 0000000000..9c5b0893ae --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/GHGHGL_2.f @@ -0,0 +1,25 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C P(3,2) +C + SUBROUTINE GHGHGL_2(S1, V3, COUP, M2, W2,S2) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*16 CI + PARAMETER (CI=(0D0,1D0)) + COMPLEX*16 COUP + REAL*8 M2 + COMPLEX*16 P2(0:3) + TYPE(ALOHA) S1 + TYPE(ALOHA) S2 + COMPLEX*16 TMP1 + TYPE(ALOHA) V3 + REAL*8 W2 + S2%P(:) = +S1%P(:)+V3%P(:) + P2(:) = -S2 % P (:) + TMP1 = (V3 % W(1)*P2(0)-V3 % W(2)*P2(1)-V3 % W(3)*P2(2)-V3 % W(4) + $ *P2(3)) + S2%W(1)= COUP*CI * TMP1*S1 % W(1) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/MP_FFV1LP0_3.f b/UNITTEST_proc/Source/DHELAS/MP_FFV1LP0_3.f new file mode 100644 index 0000000000..c35c7b0f80 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/MP_FFV1LP0_3.f @@ -0,0 +1,29 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C Gamma(3,2,1) +C + SUBROUTINE MP_FFV1LP0_3(F1, F2, COUP, M3, W3,V3) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*32 CI + PARAMETER (CI=(0Q0,1Q0)) + COMPLEX*32 COUP + TYPE(MP_ALOHA) F1 + INTEGER FLV_INDEX1 + TYPE(MP_ALOHA) F2 + INTEGER FLV_INDEX2 + REAL*16 M3 + TYPE(MP_ALOHA) V3 + REAL*16 W3 + V3%P(:) = +F1%P(:)+F2%P(:) + V3%W(1)= COUP*(-CI)*(F2 % W(3)*F1 % W(1)+F2 % W(4)*F1 % W(2)+F2 + $ % W(1)*F1 % W(3)+F2 % W(2)*F1 % W(4)) + V3%W(2)= COUP*(-CI)*(-F2 % W(4)*F1 % W(1)-F2 % W(3)*F1 % W(2)+F2 + $ % W(2)*F1 % W(3)+F2 % W(1)*F1 % W(4)) + V3%W(3)= COUP*(-CI)*(-CI*(F2 % W(4)*F1 % W(1)+F2 % W(1)*F1 % W(4) + $ )+CI*(F2 % W(3)*F1 % W(2)+F2 % W(2)*F1 % W(3))) + V3%W(4)= COUP*(-CI)*(-F2 % W(3)*F1 % W(1)-F2 % W(2)*F1 % W(4)+F2 + $ % W(4)*F1 % W(2)+F2 % W(1)*F1 % W(3)) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/MP_FFV1L_1.f b/UNITTEST_proc/Source/DHELAS/MP_FFV1L_1.f new file mode 100644 index 0000000000..56ef41d634 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/MP_FFV1L_1.f @@ -0,0 +1,51 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C Gamma(3,2,1) +C + SUBROUTINE MP_FFV1L_1(F2, V3, COUP, M1, W1,F1) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*32 CI + PARAMETER (CI=(0Q0,1Q0)) + COMPLEX*32 COUP + TYPE(MP_ALOHA) F1 + INTEGER FLV_INDEX1 + TYPE(MP_ALOHA) F2 + INTEGER FLV_INDEX2 + REAL*16 M1 + COMPLEX*32 P1(0:3) + TYPE(MP_ALOHA) V3 + REAL*16 W1 + F1%P(:) = +F2%P(:)+V3%P(:) + P1(:) = -F1 % P (:) + F1%W(1)= COUP*CI*(F2 % W(1)*(P1(0)*(-V3 % W(1)+V3 % W(4))+(P1(1) + $ *(V3 % W(2)-CI*(V3 % W(3)))+(P1(2)*(+CI*(V3 % W(2))+V3 % W(3)) + $ +P1(3)*(-V3 % W(1)+V3 % W(4)))))+(F2 % W(2)*(P1(0)*(V3 % W(2) + $ +CI*(V3 % W(3)))+(P1(1)*(-1Q0)*(V3 % W(1)+V3 % W(4))+(P1(2)*( + $ -1Q0)*(+CI*(V3 % W(1)+V3 % W(4)))+P1(3)*(V3 % W(2)+CI*(V3 % W(3) + $ )))))+M1*(F2 % W(3)*(V3 % W(1)+V3 % W(4))+F2 % W(4)*(V3 % W(2) + $ +CI*(V3 % W(3)))))) + F1%W(2)= COUP*(-CI)*(F2 % W(1)*(P1(0)*(-V3 % W(2)+CI*(V3 % W(3))) + $ +(P1(1)*(V3 % W(1)-V3 % W(4))+(P1(2)*(-CI*(V3 % W(1))+CI*(V3 % + $ W(4)))+P1(3)*(V3 % W(2)-CI*(V3 % W(3))))))+(F2 % W(2)*(P1(0) + $ *(V3 % W(1)+V3 % W(4))+(P1(1)*(-1Q0)*(V3 % W(2)+CI*(V3 % W(3))) + $ +(P1(2)*(+CI*(V3 % W(2))-V3 % W(3))-P1(3)*(V3 % W(1)+V3 % W(4))) + $ ))+M1*(F2 % W(3)*(-V3 % W(2)+CI*(V3 % W(3)))+F2 % W(4)*(-V3 % + $ W(1)+V3 % W(4))))) + F1%W(3)= COUP*(-CI)*(F2 % W(3)*(P1(0)*(V3 % W(1)+V3 % W(4)) + $ +(P1(1)*(-V3 % W(2)+CI*(V3 % W(3)))+(P1(2)*(-1Q0)*(+CI*(V3 % + $ W(2))+V3 % W(3))-P1(3)*(V3 % W(1)+V3 % W(4)))))+(F2 % W(4) + $ *(P1(0)*(V3 % W(2)+CI*(V3 % W(3)))+(P1(1)*(-V3 % W(1)+V3 % W(4)) + $ +(P1(2)*(-CI*(V3 % W(1))+CI*(V3 % W(4)))-P1(3)*(V3 % W(2)+CI + $ *(V3 % W(3))))))+M1*(F2 % W(1)*(-V3 % W(1)+V3 % W(4))+F2 % W(2) + $ *(V3 % W(2)+CI*(V3 % W(3)))))) + F1%W(4)= COUP*CI*(F2 % W(3)*(P1(0)*(-V3 % W(2)+CI*(V3 % W(3))) + $ +(P1(1)*(V3 % W(1)+V3 % W(4))+(P1(2)*(-1Q0)*(+CI*(V3 % W(1)+V3 + $ % W(4)))+P1(3)*(-V3 % W(2)+CI*(V3 % W(3))))))+(F2 % W(4)*(P1(0) + $ *(-V3 % W(1)+V3 % W(4))+(P1(1)*(V3 % W(2)+CI*(V3 % W(3)))+(P1(2) + $ *(-CI*(V3 % W(2))+V3 % W(3))+P1(3)*(-V3 % W(1)+V3 % W(4)))))+M1 + $ *(F2 % W(1)*(-V3 % W(2)+CI*(V3 % W(3)))+F2 % W(2)*(V3 % W(1)+V3 + $ % W(4))))) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/MP_FFV1L_2.f b/UNITTEST_proc/Source/DHELAS/MP_FFV1L_2.f new file mode 100644 index 0000000000..e79f2345a6 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/MP_FFV1L_2.f @@ -0,0 +1,51 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C Gamma(3,2,1) +C + SUBROUTINE MP_FFV1L_2(F1, V3, COUP, M2, W2,F2) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*32 CI + PARAMETER (CI=(0Q0,1Q0)) + COMPLEX*32 COUP + TYPE(MP_ALOHA) F1 + INTEGER FLV_INDEX1 + TYPE(MP_ALOHA) F2 + INTEGER FLV_INDEX2 + REAL*16 M2 + COMPLEX*32 P2(0:3) + TYPE(MP_ALOHA) V3 + REAL*16 W2 + F2%P(:) = +F1%P(:)+V3%P(:) + P2(:) = -F2 % P (:) + F2%W(1)= COUP*CI*(F1 % W(1)*(P2(0)*(V3 % W(1)+V3 % W(4))+(P2(1) + $ *(-1Q0)*(V3 % W(2)+CI*(V3 % W(3)))+(P2(2)*(+CI*(V3 % W(2))-V3 % + $ W(3))-P2(3)*(V3 % W(1)+V3 % W(4)))))+(F1 % W(2)*(P2(0)*(V3 % + $ W(2)-CI*(V3 % W(3)))+(P2(1)*(-V3 % W(1)+V3 % W(4))+(P2(2)*(+CI + $ *(V3 % W(1))-CI*(V3 % W(4)))+P2(3)*(-V3 % W(2)+CI*(V3 % W(3))))) + $ )+M2*(F1 % W(3)*(V3 % W(1)-V3 % W(4))+F1 % W(4)*(-V3 % W(2)+CI + $ *(V3 % W(3)))))) + F2%W(2)= COUP*(-CI)*(F1 % W(1)*(P2(0)*(-1Q0)*(V3 % W(2)+CI*(V3 % + $ W(3)))+(P2(1)*(V3 % W(1)+V3 % W(4))+(P2(2)*(+CI*(V3 % W(1)+V3 + $ % W(4)))-P2(3)*(V3 % W(2)+CI*(V3 % W(3))))))+(F1 % W(2)*(P2(0) + $ *(-V3 % W(1)+V3 % W(4))+(P2(1)*(V3 % W(2)-CI*(V3 % W(3)))+(P2(2) + $ *(+CI*(V3 % W(2))+V3 % W(3))+P2(3)*(-V3 % W(1)+V3 % W(4)))))+M2 + $ *(F1 % W(3)*(V3 % W(2)+CI*(V3 % W(3)))-F1 % W(4)*(V3 % W(1)+V3 + $ % W(4))))) + F2%W(3)= COUP*(-CI)*(F1 % W(3)*(P2(0)*(-V3 % W(1)+V3 % W(4)) + $ +(P2(1)*(V3 % W(2)+CI*(V3 % W(3)))+(P2(2)*(-CI*(V3 % W(2))+V3 % + $ W(3))+P2(3)*(-V3 % W(1)+V3 % W(4)))))+(F1 % W(4)*(P2(0)*(V3 % + $ W(2)-CI*(V3 % W(3)))+(P2(1)*(-1Q0)*(V3 % W(1)+V3 % W(4))+(P2(2) + $ *(+CI*(V3 % W(1)+V3 % W(4)))+P2(3)*(V3 % W(2)-CI*(V3 % W(3)))))) + $ +M2*(F1 % W(1)*(-1Q0)*(V3 % W(1)+V3 % W(4))+F1 % W(2)*(-V3 % + $ W(2)+CI*(V3 % W(3)))))) + F2%W(4)= COUP*CI*(F1 % W(3)*(P2(0)*(-1Q0)*(V3 % W(2)+CI*(V3 % + $ W(3)))+(P2(1)*(V3 % W(1)-V3 % W(4))+(P2(2)*(+CI*(V3 % W(1))-CI + $ *(V3 % W(4)))+P2(3)*(V3 % W(2)+CI*(V3 % W(3))))))+(F1 % W(4) + $ *(P2(0)*(V3 % W(1)+V3 % W(4))+(P2(1)*(-V3 % W(2)+CI*(V3 % W(3))) + $ +(P2(2)*(-1Q0)*(+CI*(V3 % W(2))+V3 % W(3))-P2(3)*(V3 % W(1)+V3 + $ % W(4)))))+M2*(F1 % W(1)*(V3 % W(2)+CI*(V3 % W(3)))+F1 % W(2) + $ *(V3 % W(1)-V3 % W(4))))) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/MP_FFV1P0_3.f b/UNITTEST_proc/Source/DHELAS/MP_FFV1P0_3.f new file mode 100644 index 0000000000..64bbad5858 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/MP_FFV1P0_3.f @@ -0,0 +1,40 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C Gamma(3,2,1) +C + SUBROUTINE MP_FFV1P0_3(F1, F2, COUP, M3, W3,V3) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*32 CI + PARAMETER (CI=(0Q0,1Q0)) + COMPLEX*32 COUP + TYPE(MP_ALOHA) F1 + INTEGER FLV_INDEX1 + TYPE(MP_ALOHA) F2 + INTEGER FLV_INDEX2 + REAL*16 M3 + REAL*16 P3(0:3) + TYPE(MP_ALOHA) V3 + REAL*16 W3 + COMPLEX*32 DENOM + V3%P(:) = +F1%P(:)+F2%P(:) + P3(:) = -V3 % P (:) + FLV_INDEX1 = F1 %FLV_INDEX + FLV_INDEX2 = F2 %FLV_INDEX + IF(FLV_INDEX1.NE.FLV_INDEX2.OR.FLV_INDEX1.EQ.0)THEN + V3%W(:) = (0D0,0D0) + RETURN + ENDIF + DENOM = COUP/(P3(0)**2-P3(1)**2-P3(2)**2-P3(3)**2 - M3 * (M3 -CI + $ * W3)) + V3%W(1)= DENOM*(-CI)*(F2 % W(3)*F1 % W(1)+F2 % W(4)*F1 % W(2)+F2 + $ % W(1)*F1 % W(3)+F2 % W(2)*F1 % W(4)) + V3%W(2)= DENOM*(-CI)*(-F2 % W(4)*F1 % W(1)-F2 % W(3)*F1 % W(2) + $ +F2 % W(2)*F1 % W(3)+F2 % W(1)*F1 % W(4)) + V3%W(3)= DENOM*(-CI)*(-CI*(F2 % W(4)*F1 % W(1)+F2 % W(1)*F1 % + $ W(4))+CI*(F2 % W(3)*F1 % W(2)+F2 % W(2)*F1 % W(3))) + V3%W(4)= DENOM*(-CI)*(-F2 % W(3)*F1 % W(1)-F2 % W(2)*F1 % W(4) + $ +F2 % W(4)*F1 % W(2)+F2 % W(1)*F1 % W(3)) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/MP_FFV1_0.f b/UNITTEST_proc/Source/DHELAS/MP_FFV1_0.f new file mode 100644 index 0000000000..83d839b2ad --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/MP_FFV1_0.f @@ -0,0 +1,33 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C Gamma(3,2,1) +C + SUBROUTINE MP_FFV1_0(F1, F2, V3, COUP,VERTEX) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*32 CI + PARAMETER (CI=(0Q0,1Q0)) + COMPLEX*32 COUP + TYPE(MP_ALOHA) F1 + INTEGER FLV_INDEX1 + TYPE(MP_ALOHA) F2 + INTEGER FLV_INDEX2 + COMPLEX*32 TMP10 + TYPE(MP_ALOHA) V3 + COMPLEX*32 VERTEX + FLV_INDEX1 = F1 %FLV_INDEX + FLV_INDEX2 = F2 %FLV_INDEX + IF(FLV_INDEX1.NE.FLV_INDEX2.OR.FLV_INDEX1.EQ.0)THEN + VERTEX = (0D0,0D0) + RETURN + ENDIF + TMP10 = (F1 % W(1)*(F2 % W(3)*(V3 % W(1)+V3 % W(4))+F2 % W(4) + $ *(V3 % W(2)+CI*(V3 % W(3))))+(F1 % W(2)*(F2 % W(3)*(V3 % W(2) + $ -CI*(V3 % W(3)))+F2 % W(4)*(V3 % W(1)-V3 % W(4)))+(F1 % W(3) + $ *(F2 % W(1)*(V3 % W(1)-V3 % W(4))-F2 % W(2)*(V3 % W(2)+CI*(V3 % + $ W(3))))+F1 % W(4)*(F2 % W(1)*(-V3 % W(2)+CI*(V3 % W(3)))+F2 % + $ W(2)*(V3 % W(1)+V3 % W(4)))))) + VERTEX = COUP*(-CI * TMP10) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/MP_FFV1_1.f b/UNITTEST_proc/Source/DHELAS/MP_FFV1_1.f new file mode 100644 index 0000000000..b4489811e1 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/MP_FFV1_1.f @@ -0,0 +1,55 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C Gamma(3,2,1) +C + SUBROUTINE MP_FFV1_1(F2, V3, COUP, M1, W1,F1) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*32 CI + PARAMETER (CI=(0Q0,1Q0)) + COMPLEX*32 COUP + TYPE(MP_ALOHA) F1 + INTEGER FLV_INDEX1 + TYPE(MP_ALOHA) F2 + INTEGER FLV_INDEX2 + REAL*16 M1 + REAL*16 P1(0:3) + TYPE(MP_ALOHA) V3 + REAL*16 W1 + COMPLEX*32 DENOM + F1%P(:) = +F2%P(:)+V3%P(:) + P1(:) = -F1 % P (:) + F1 % FLV_INDEX = F2 % FLV_INDEX + DENOM = COUP/(P1(0)**2-P1(1)**2-P1(2)**2-P1(3)**2 - M1 * (M1 -CI + $ * W1)) + F1%W(1)= DENOM*CI*(F2 % W(1)*(P1(0)*(-V3 % W(1)+V3 % W(4))+(P1(1) + $ *(V3 % W(2)-CI*(V3 % W(3)))+(P1(2)*(+CI*(V3 % W(2))+V3 % W(3)) + $ +P1(3)*(-V3 % W(1)+V3 % W(4)))))+(F2 % W(2)*(P1(0)*(V3 % W(2) + $ +CI*(V3 % W(3)))+(P1(1)*(-1Q0)*(V3 % W(1)+V3 % W(4))+(P1(2)*( + $ -1Q0)*(+CI*(V3 % W(1)+V3 % W(4)))+P1(3)*(V3 % W(2)+CI*(V3 % W(3) + $ )))))+M1*(F2 % W(3)*(V3 % W(1)+V3 % W(4))+F2 % W(4)*(V3 % W(2) + $ +CI*(V3 % W(3)))))) + F1%W(2)= DENOM*(-CI)*(F2 % W(1)*(P1(0)*(-V3 % W(2)+CI*(V3 % W(3)) + $ )+(P1(1)*(V3 % W(1)-V3 % W(4))+(P1(2)*(-CI*(V3 % W(1))+CI*(V3 % + $ W(4)))+P1(3)*(V3 % W(2)-CI*(V3 % W(3))))))+(F2 % W(2)*(P1(0) + $ *(V3 % W(1)+V3 % W(4))+(P1(1)*(-1Q0)*(V3 % W(2)+CI*(V3 % W(3))) + $ +(P1(2)*(+CI*(V3 % W(2))-V3 % W(3))-P1(3)*(V3 % W(1)+V3 % W(4))) + $ ))+M1*(F2 % W(3)*(-V3 % W(2)+CI*(V3 % W(3)))+F2 % W(4)*(-V3 % + $ W(1)+V3 % W(4))))) + F1%W(3)= DENOM*(-CI)*(F2 % W(3)*(P1(0)*(V3 % W(1)+V3 % W(4)) + $ +(P1(1)*(-V3 % W(2)+CI*(V3 % W(3)))+(P1(2)*(-1Q0)*(+CI*(V3 % + $ W(2))+V3 % W(3))-P1(3)*(V3 % W(1)+V3 % W(4)))))+(F2 % W(4) + $ *(P1(0)*(V3 % W(2)+CI*(V3 % W(3)))+(P1(1)*(-V3 % W(1)+V3 % W(4)) + $ +(P1(2)*(-CI*(V3 % W(1))+CI*(V3 % W(4)))-P1(3)*(V3 % W(2)+CI + $ *(V3 % W(3))))))+M1*(F2 % W(1)*(-V3 % W(1)+V3 % W(4))+F2 % W(2) + $ *(V3 % W(2)+CI*(V3 % W(3)))))) + F1%W(4)= DENOM*CI*(F2 % W(3)*(P1(0)*(-V3 % W(2)+CI*(V3 % W(3))) + $ +(P1(1)*(V3 % W(1)+V3 % W(4))+(P1(2)*(-1Q0)*(+CI*(V3 % W(1)+V3 + $ % W(4)))+P1(3)*(-V3 % W(2)+CI*(V3 % W(3))))))+(F2 % W(4)*(P1(0) + $ *(-V3 % W(1)+V3 % W(4))+(P1(1)*(V3 % W(2)+CI*(V3 % W(3)))+(P1(2) + $ *(-CI*(V3 % W(2))+V3 % W(3))+P1(3)*(-V3 % W(1)+V3 % W(4)))))+M1 + $ *(F2 % W(1)*(-V3 % W(2)+CI*(V3 % W(3)))+F2 % W(2)*(V3 % W(1)+V3 + $ % W(4))))) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/MP_FFV1_2.f b/UNITTEST_proc/Source/DHELAS/MP_FFV1_2.f new file mode 100644 index 0000000000..1b1025ee3b --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/MP_FFV1_2.f @@ -0,0 +1,55 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C Gamma(3,2,1) +C + SUBROUTINE MP_FFV1_2(F1, V3, COUP, M2, W2,F2) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*32 CI + PARAMETER (CI=(0Q0,1Q0)) + COMPLEX*32 COUP + TYPE(MP_ALOHA) F1 + INTEGER FLV_INDEX1 + TYPE(MP_ALOHA) F2 + INTEGER FLV_INDEX2 + REAL*16 M2 + REAL*16 P2(0:3) + TYPE(MP_ALOHA) V3 + REAL*16 W2 + COMPLEX*32 DENOM + F2%P(:) = +F1%P(:)+V3%P(:) + P2(:) = -F2 % P (:) + F2 % FLV_INDEX = F1 % FLV_INDEX + DENOM = COUP/(P2(0)**2-P2(1)**2-P2(2)**2-P2(3)**2 - M2 * (M2 -CI + $ * W2)) + F2%W(1)= DENOM*CI*(F1 % W(1)*(P2(0)*(V3 % W(1)+V3 % W(4))+(P2(1) + $ *(-1Q0)*(V3 % W(2)+CI*(V3 % W(3)))+(P2(2)*(+CI*(V3 % W(2))-V3 % + $ W(3))-P2(3)*(V3 % W(1)+V3 % W(4)))))+(F1 % W(2)*(P2(0)*(V3 % + $ W(2)-CI*(V3 % W(3)))+(P2(1)*(-V3 % W(1)+V3 % W(4))+(P2(2)*(+CI + $ *(V3 % W(1))-CI*(V3 % W(4)))+P2(3)*(-V3 % W(2)+CI*(V3 % W(3))))) + $ )+M2*(F1 % W(3)*(V3 % W(1)-V3 % W(4))+F1 % W(4)*(-V3 % W(2)+CI + $ *(V3 % W(3)))))) + F2%W(2)= DENOM*(-CI)*(F1 % W(1)*(P2(0)*(-1Q0)*(V3 % W(2)+CI*(V3 + $ % W(3)))+(P2(1)*(V3 % W(1)+V3 % W(4))+(P2(2)*(+CI*(V3 % W(1) + $ +V3 % W(4)))-P2(3)*(V3 % W(2)+CI*(V3 % W(3))))))+(F1 % W(2) + $ *(P2(0)*(-V3 % W(1)+V3 % W(4))+(P2(1)*(V3 % W(2)-CI*(V3 % W(3))) + $ +(P2(2)*(+CI*(V3 % W(2))+V3 % W(3))+P2(3)*(-V3 % W(1)+V3 % W(4)) + $ )))+M2*(F1 % W(3)*(V3 % W(2)+CI*(V3 % W(3)))-F1 % W(4)*(V3 % + $ W(1)+V3 % W(4))))) + F2%W(3)= DENOM*(-CI)*(F1 % W(3)*(P2(0)*(-V3 % W(1)+V3 % W(4)) + $ +(P2(1)*(V3 % W(2)+CI*(V3 % W(3)))+(P2(2)*(-CI*(V3 % W(2))+V3 % + $ W(3))+P2(3)*(-V3 % W(1)+V3 % W(4)))))+(F1 % W(4)*(P2(0)*(V3 % + $ W(2)-CI*(V3 % W(3)))+(P2(1)*(-1Q0)*(V3 % W(1)+V3 % W(4))+(P2(2) + $ *(+CI*(V3 % W(1)+V3 % W(4)))+P2(3)*(V3 % W(2)-CI*(V3 % W(3)))))) + $ +M2*(F1 % W(1)*(-1Q0)*(V3 % W(1)+V3 % W(4))+F1 % W(2)*(-V3 % + $ W(2)+CI*(V3 % W(3)))))) + F2%W(4)= DENOM*CI*(F1 % W(3)*(P2(0)*(-1Q0)*(V3 % W(2)+CI*(V3 % + $ W(3)))+(P2(1)*(V3 % W(1)-V3 % W(4))+(P2(2)*(+CI*(V3 % W(1))-CI + $ *(V3 % W(4)))+P2(3)*(V3 % W(2)+CI*(V3 % W(3))))))+(F1 % W(4) + $ *(P2(0)*(V3 % W(1)+V3 % W(4))+(P2(1)*(-V3 % W(2)+CI*(V3 % W(3))) + $ +(P2(2)*(-1Q0)*(+CI*(V3 % W(2))+V3 % W(3))-P2(3)*(V3 % W(1)+V3 + $ % W(4)))))+M2*(F1 % W(1)*(V3 % W(2)+CI*(V3 % W(3)))+F1 % W(2) + $ *(V3 % W(1)-V3 % W(4))))) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/MP_GHGHGL_1.f b/UNITTEST_proc/Source/DHELAS/MP_GHGHGL_1.f new file mode 100644 index 0000000000..6b7a30b06b --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/MP_GHGHGL_1.f @@ -0,0 +1,25 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C P(3,2) +C + SUBROUTINE MP_GHGHGL_1(S2, V3, COUP, M1, W1,S1) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*32 CI + PARAMETER (CI=(0Q0,1Q0)) + COMPLEX*32 COUP + REAL*16 M1 + COMPLEX*32 P2(0:3) + TYPE(MP_ALOHA) S1 + TYPE(MP_ALOHA) S2 + COMPLEX*32 TMP1 + TYPE(MP_ALOHA) V3 + REAL*16 W1 + P2(:) = S2 % P (:) + S1%P(:) = +S2%P(:)+V3%P(:) + TMP1 = (V3 % W(1)*P2(0)-V3 % W(2)*P2(1)-V3 % W(3)*P2(2)-V3 % W(4) + $ *P2(3)) + S1%W(1)= COUP*CI * TMP1*S2 % W(1) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/MP_GHGHGL_2.f b/UNITTEST_proc/Source/DHELAS/MP_GHGHGL_2.f new file mode 100644 index 0000000000..86b662cbb3 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/MP_GHGHGL_2.f @@ -0,0 +1,25 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C P(3,2) +C + SUBROUTINE MP_GHGHGL_2(S1, V3, COUP, M2, W2,S2) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*32 CI + PARAMETER (CI=(0Q0,1Q0)) + COMPLEX*32 COUP + REAL*16 M2 + COMPLEX*32 P2(0:3) + TYPE(MP_ALOHA) S1 + TYPE(MP_ALOHA) S2 + COMPLEX*32 TMP1 + TYPE(MP_ALOHA) V3 + REAL*16 W2 + S2%P(:) = +S1%P(:)+V3%P(:) + P2(:) = -S2 % P (:) + TMP1 = (V3 % W(1)*P2(0)-V3 % W(2)*P2(1)-V3 % W(3)*P2(2)-V3 % W(4) + $ *P2(3)) + S2%W(1)= COUP*CI * TMP1*S1 % W(1) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/MP_R2_GG_1_0.f b/UNITTEST_proc/Source/DHELAS/MP_R2_GG_1_0.f new file mode 100644 index 0000000000..7c1716a229 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/MP_R2_GG_1_0.f @@ -0,0 +1,24 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C P(-1,1)*P(-1,1)*Metric(1,2) +C + SUBROUTINE MP_R2_GG_1_0(V1, V2, COUP,VERTEX) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*32 CI + PARAMETER (CI=(0Q0,1Q0)) + COMPLEX*32 COUP + REAL*16 P1(0:3) + COMPLEX*32 TMP12 + COMPLEX*32 TMP3 + TYPE(MP_ALOHA) V1 + TYPE(MP_ALOHA) V2 + COMPLEX*32 VERTEX + P1(:) = V1 % P (:) + TMP12 = (P1(0)*P1(0)-P1(1)*P1(1)-P1(2)*P1(2)-P1(3)*P1(3)) + TMP3 = (V2 % W(1)*V1 % W(1)-V2 % W(2)*V1 % W(2)-V2 % W(3)*V1 % + $ W(3)-V2 % W(4)*V1 % W(4)) + VERTEX = COUP*(-CI * TMP3*TMP12) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/MP_R2_GG_1_R2_GG_2_0.f b/UNITTEST_proc/Source/DHELAS/MP_R2_GG_1_R2_GG_2_0.f new file mode 100644 index 0000000000..2e22a66857 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/MP_R2_GG_1_R2_GG_2_0.f @@ -0,0 +1,31 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +Coup(1) * (P(-1,1)*P(-1,1)*Metric(1,2)) + Coup(2) * (P(1,1)*P(2,1)) +C + SUBROUTINE MP_R2_GG_1_R2_GG_2_0(V1, V2, COUP1, COUP2,VERTEX) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*32 CI + PARAMETER (CI=(0Q0,1Q0)) + COMPLEX*32 COUP1 + COMPLEX*32 COUP2 + REAL*16 P1(0:3) + COMPLEX*32 TMP12 + COMPLEX*32 TMP13 + COMPLEX*32 TMP3 + COMPLEX*32 TMP5 + TYPE(MP_ALOHA) V1 + TYPE(MP_ALOHA) V2 + COMPLEX*32 VERTEX + P1(:) = V1 % P (:) + TMP12 = (P1(0)*P1(0)-P1(1)*P1(1)-P1(2)*P1(2)-P1(3)*P1(3)) + TMP13 = (P1(0)*V1 % W(1)-P1(1)*V1 % W(2)-P1(2)*V1 % W(3)-P1(3) + $ *V1 % W(4)) + TMP3 = (V2 % W(1)*V1 % W(1)-V2 % W(2)*V1 % W(2)-V2 % W(3)*V1 % + $ W(3)-V2 % W(4)*V1 % W(4)) + TMP5 = (V2 % W(1)*P1(0)-V2 % W(2)*P1(1)-V2 % W(3)*P1(2)-V2 % W(4) + $ *P1(3)) + VERTEX = (-1Q0)*(+CI*(TMP3*TMP12*COUP1+TMP5*TMP13*COUP2)) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/MP_R2_GG_1_R2_GG_3_0.f b/UNITTEST_proc/Source/DHELAS/MP_R2_GG_1_R2_GG_3_0.f new file mode 100644 index 0000000000..bc0230d8be --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/MP_R2_GG_1_R2_GG_3_0.f @@ -0,0 +1,25 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +Coup(1) * (P(-1,1)*P(-1,1)*Metric(1,2)) + Coup(2) * (Metric(1,2)) +C + SUBROUTINE MP_R2_GG_1_R2_GG_3_0(V1, V2, COUP1, COUP2,VERTEX) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*32 CI + PARAMETER (CI=(0Q0,1Q0)) + COMPLEX*32 COUP1 + COMPLEX*32 COUP2 + REAL*16 P1(0:3) + COMPLEX*32 TMP12 + COMPLEX*32 TMP3 + TYPE(MP_ALOHA) V1 + TYPE(MP_ALOHA) V2 + COMPLEX*32 VERTEX + P1(:) = V1 % P (:) + TMP12 = (P1(0)*P1(0)-P1(1)*P1(1)-P1(2)*P1(2)-P1(3)*P1(3)) + TMP3 = (V2 % W(1)*V1 % W(1)-V2 % W(2)*V1 % W(2)-V2 % W(3)*V1 % + $ W(3)-V2 % W(4)*V1 % W(4)) + VERTEX = -TMP3*(+CI*(TMP12*COUP1+COUP2)) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/MP_R2_GG_2_0.f b/UNITTEST_proc/Source/DHELAS/MP_R2_GG_2_0.f new file mode 100644 index 0000000000..859a9815e7 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/MP_R2_GG_2_0.f @@ -0,0 +1,25 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C P(1,1)*P(2,1) +C + SUBROUTINE MP_R2_GG_2_0(V1, V2, COUP,VERTEX) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*32 CI + PARAMETER (CI=(0Q0,1Q0)) + COMPLEX*32 COUP + REAL*16 P1(0:3) + COMPLEX*32 TMP13 + COMPLEX*32 TMP5 + TYPE(MP_ALOHA) V1 + TYPE(MP_ALOHA) V2 + COMPLEX*32 VERTEX + P1(:) = V1 % P (:) + TMP13 = (P1(0)*V1 % W(1)-P1(1)*V1 % W(2)-P1(2)*V1 % W(3)-P1(3) + $ *V1 % W(4)) + TMP5 = (V2 % W(1)*P1(0)-V2 % W(2)*P1(1)-V2 % W(3)*P1(2)-V2 % W(4) + $ *P1(3)) + VERTEX = COUP*(-CI * TMP5*TMP13) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/MP_R2_GG_3_0.f b/UNITTEST_proc/Source/DHELAS/MP_R2_GG_3_0.f new file mode 100644 index 0000000000..bc59c0387b --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/MP_R2_GG_3_0.f @@ -0,0 +1,20 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C Metric(1,2) +C + SUBROUTINE MP_R2_GG_3_0(V1, V2, COUP,VERTEX) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*32 CI + PARAMETER (CI=(0Q0,1Q0)) + COMPLEX*32 COUP + COMPLEX*32 TMP3 + TYPE(MP_ALOHA) V1 + TYPE(MP_ALOHA) V2 + COMPLEX*32 VERTEX + TMP3 = (V2 % W(1)*V1 % W(1)-V2 % W(2)*V1 % W(2)-V2 % W(3)*V1 % + $ W(3)-V2 % W(4)*V1 % W(4)) + VERTEX = COUP*(-CI * TMP3) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/MP_R2_QQ_1_0.f b/UNITTEST_proc/Source/DHELAS/MP_R2_QQ_1_0.f new file mode 100644 index 0000000000..9e86ca3048 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/MP_R2_QQ_1_0.f @@ -0,0 +1,33 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C P(-1,1)*Gamma(-1,2,1) +C + SUBROUTINE MP_R2_QQ_1_0(F1, F2, COUP,VERTEX) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*32 CI + PARAMETER (CI=(0Q0,1Q0)) + COMPLEX*32 COUP + TYPE(MP_ALOHA) F1 + INTEGER FLV_INDEX1 + TYPE(MP_ALOHA) F2 + INTEGER FLV_INDEX2 + REAL*16 P1(0:3) + COMPLEX*32 TMP14 + COMPLEX*32 VERTEX + P1(:) = F1 % P (:) + FLV_INDEX1 = F1 %FLV_INDEX + FLV_INDEX2 = F2 %FLV_INDEX + IF(FLV_INDEX1.NE.FLV_INDEX2.OR.FLV_INDEX1.EQ.0)THEN + VERTEX = (0D0,0D0) + RETURN + ENDIF + TMP14 = (F1 % W(1)*(F2 % W(3)*(P1(0)+P1(3))+F2 % W(4)*(P1(1)+CI + $ *(P1(2))))+(F1 % W(2)*(F2 % W(3)*(P1(1)-CI*(P1(2)))+F2 % W(4) + $ *(P1(0)-P1(3)))+(F1 % W(3)*(F2 % W(1)*(P1(0)-P1(3))-F2 % W(2) + $ *(P1(1)+CI*(P1(2))))+F1 % W(4)*(F2 % W(1)*(-P1(1)+CI*(P1(2))) + $ +F2 % W(2)*(P1(0)+P1(3)))))) + VERTEX = COUP*(-CI * TMP14) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/MP_R2_QQ_1_R2_QQ_2_0.f b/UNITTEST_proc/Source/DHELAS/MP_R2_QQ_1_R2_QQ_2_0.f new file mode 100644 index 0000000000..59ab34f5fb --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/MP_R2_QQ_1_R2_QQ_2_0.f @@ -0,0 +1,37 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +Coup(1) * (P(-1,1)*Gamma(-1,2,1)) + Coup(2) * (Identity(1,2)) +C + SUBROUTINE MP_R2_QQ_1_R2_QQ_2_0(F1, F2, COUP1, COUP2,VERTEX) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*32 CI + PARAMETER (CI=(0Q0,1Q0)) + COMPLEX*32 COUP1 + COMPLEX*32 COUP2 + TYPE(MP_ALOHA) F1 + INTEGER FLV_INDEX1 + TYPE(MP_ALOHA) F2 + INTEGER FLV_INDEX2 + REAL*16 P1(0:3) + COMPLEX*32 TMP15 + COMPLEX*32 TMP16 + COMPLEX*32 VERTEX + P1(:) = F1 % P (:) + FLV_INDEX1 = F1 %FLV_INDEX + FLV_INDEX2 = F2 %FLV_INDEX + IF(FLV_INDEX1.NE.FLV_INDEX2.OR.FLV_INDEX1.EQ.0)THEN + VERTEX = (0D0,0D0) + RETURN + ENDIF + TMP15 = (F2 % W(1)*F1 % W(1)+F2 % W(2)*F1 % W(2)+F2 % W(3)*F1 % + $ W(3)+F2 % W(4)*F1 % W(4)) + TMP16 = (F1 % W(1)*(F2 % W(3)*(P1(0)+P1(3))+F2 % W(4)*(P1(1)+CI + $ *(P1(2))))+(F1 % W(2)*(F2 % W(3)*(P1(1)-CI*(P1(2)))+F2 % W(4) + $ *(P1(0)-P1(3)))+(F1 % W(3)*(F2 % W(1)*(P1(0)-P1(3))-F2 % W(2) + $ *(P1(1)+CI*(P1(2))))+F1 % W(4)*(F2 % W(1)*(-P1(1)+CI*(P1(2))) + $ +F2 % W(2)*(P1(0)+P1(3)))))) + VERTEX = (-1Q0)*(+CI*(COUP1*TMP16+TMP15*COUP2)) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/MP_R2_QQ_2_0.f b/UNITTEST_proc/Source/DHELAS/MP_R2_QQ_2_0.f new file mode 100644 index 0000000000..f499f9ddeb --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/MP_R2_QQ_2_0.f @@ -0,0 +1,28 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C Identity(1,2) +C + SUBROUTINE MP_R2_QQ_2_0(F1, F2, COUP,VERTEX) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*32 CI + PARAMETER (CI=(0Q0,1Q0)) + COMPLEX*32 COUP + TYPE(MP_ALOHA) F1 + INTEGER FLV_INDEX1 + TYPE(MP_ALOHA) F2 + INTEGER FLV_INDEX2 + COMPLEX*32 TMP15 + COMPLEX*32 VERTEX + FLV_INDEX1 = F1 %FLV_INDEX + FLV_INDEX2 = F2 %FLV_INDEX + IF(FLV_INDEX1.NE.FLV_INDEX2.OR.FLV_INDEX1.EQ.0)THEN + VERTEX = (0D0,0D0) + RETURN + ENDIF + TMP15 = (F2 % W(1)*F1 % W(1)+F2 % W(2)*F1 % W(2)+F2 % W(3)*F1 % + $ W(3)+F2 % W(4)*F1 % W(4)) + VERTEX = COUP*(-CI * TMP15) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/MP_VVV1LP0_1.f b/UNITTEST_proc/Source/DHELAS/MP_VVV1LP0_1.f new file mode 100644 index 0000000000..42b5bf02c9 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/MP_VVV1LP0_1.f @@ -0,0 +1,49 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C P(3,1)*Metric(1,2) - P(3,2)*Metric(1,2) - P(2,1)*Metric(1,3) + +C P(2,3)*Metric(1,3) + P(1,2)*Metric(2,3) - P(1,3)*Metric(2,3) +C + SUBROUTINE MP_VVV1LP0_1(V2, V3, COUP, M1, W1,V1) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*32 CI + PARAMETER (CI=(0Q0,1Q0)) + COMPLEX*32 COUP + REAL*16 M1 + COMPLEX*32 P1(0:3) + COMPLEX*32 P2(0:3) + COMPLEX*32 P3(0:3) + COMPLEX*32 TMP0 + COMPLEX*32 TMP1 + COMPLEX*32 TMP5 + COMPLEX*32 TMP6 + COMPLEX*32 TMP8 + TYPE(MP_ALOHA) V1 + TYPE(MP_ALOHA) V2 + TYPE(MP_ALOHA) V3 + REAL*16 W1 + P2(:) = V2 % P (:) + P3(:) = V3 % P (:) + V1%P(:) = +V2%P(:)+V3%P(:) + P1(:) = -V1 % P (:) + TMP0 = (V3 % W(1)*P1(0)-V3 % W(2)*P1(1)-V3 % W(3)*P1(2)-V3 % W(4) + $ *P1(3)) + TMP1 = (V3 % W(1)*P2(0)-V3 % W(2)*P2(1)-V3 % W(3)*P2(2)-V3 % W(4) + $ *P2(3)) + TMP5 = (V2 % W(1)*P1(0)-V2 % W(2)*P1(1)-V2 % W(3)*P1(2)-V2 % W(4) + $ *P1(3)) + TMP6 = (V2 % W(1)*P3(0)-V2 % W(2)*P3(1)-V2 % W(3)*P3(2)-V2 % W(4) + $ *P3(3)) + TMP8 = (V2 % W(1)*V3 % W(1)-V2 % W(2)*V3 % W(2)-V2 % W(3)*V3 % + $ W(3)-V2 % W(4)*V3 % W(4)) + V1%W(1)= COUP*(TMP8*(-CI*(P2(0))+CI*(P3(0)))+(V2 % W(1)*(-CI + $ *(TMP0)+CI*(TMP1))+V3 % W(1)*(+CI*(TMP5)-CI*(TMP6)))) + V1%W(2)= COUP*(TMP8*(-CI*(P2(1))+CI*(P3(1)))+(V2 % W(2)*(-CI + $ *(TMP0)+CI*(TMP1))+V3 % W(2)*(+CI*(TMP5)-CI*(TMP6)))) + V1%W(3)= COUP*(TMP8*(-CI*(P2(2))+CI*(P3(2)))+(V2 % W(3)*(-CI + $ *(TMP0)+CI*(TMP1))+V3 % W(3)*(+CI*(TMP5)-CI*(TMP6)))) + V1%W(4)= COUP*(TMP8*(-CI*(P2(3))+CI*(P3(3)))+(V2 % W(4)*(-CI + $ *(TMP0)+CI*(TMP1))+V3 % W(4)*(+CI*(TMP5)-CI*(TMP6)))) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/MP_VVV1P0_1.f b/UNITTEST_proc/Source/DHELAS/MP_VVV1P0_1.f new file mode 100644 index 0000000000..1e0ae5bda3 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/MP_VVV1P0_1.f @@ -0,0 +1,52 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C P(3,1)*Metric(1,2) - P(3,2)*Metric(1,2) - P(2,1)*Metric(1,3) + +C P(2,3)*Metric(1,3) + P(1,2)*Metric(2,3) - P(1,3)*Metric(2,3) +C + SUBROUTINE MP_VVV1P0_1(V2, V3, COUP, M1, W1,V1) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*32 CI + PARAMETER (CI=(0Q0,1Q0)) + COMPLEX*32 COUP + REAL*16 M1 + REAL*16 P1(0:3) + REAL*16 P2(0:3) + REAL*16 P3(0:3) + COMPLEX*32 TMP0 + COMPLEX*32 TMP1 + COMPLEX*32 TMP5 + COMPLEX*32 TMP6 + COMPLEX*32 TMP8 + TYPE(MP_ALOHA) V1 + TYPE(MP_ALOHA) V2 + TYPE(MP_ALOHA) V3 + REAL*16 W1 + COMPLEX*32 DENOM + P2(:) = V2 % P (:) + P3(:) = V3 % P (:) + V1%P(:) = +V2%P(:)+V3%P(:) + P1(:) = -V1 % P (:) + TMP0 = (V3 % W(1)*P1(0)-V3 % W(2)*P1(1)-V3 % W(3)*P1(2)-V3 % W(4) + $ *P1(3)) + TMP1 = (V3 % W(1)*P2(0)-V3 % W(2)*P2(1)-V3 % W(3)*P2(2)-V3 % W(4) + $ *P2(3)) + TMP5 = (V2 % W(1)*P1(0)-V2 % W(2)*P1(1)-V2 % W(3)*P1(2)-V2 % W(4) + $ *P1(3)) + TMP6 = (V2 % W(1)*P3(0)-V2 % W(2)*P3(1)-V2 % W(3)*P3(2)-V2 % W(4) + $ *P3(3)) + TMP8 = (V2 % W(1)*V3 % W(1)-V2 % W(2)*V3 % W(2)-V2 % W(3)*V3 % + $ W(3)-V2 % W(4)*V3 % W(4)) + DENOM = COUP/(P1(0)**2-P1(1)**2-P1(2)**2-P1(3)**2 - M1 * (M1 -CI + $ * W1)) + V1%W(1)= DENOM*(TMP8*(-CI*(P2(0))+CI*(P3(0)))+(V2 % W(1)*(-CI + $ *(TMP0)+CI*(TMP1))+V3 % W(1)*(+CI*(TMP5)-CI*(TMP6)))) + V1%W(2)= DENOM*(TMP8*(-CI*(P2(1))+CI*(P3(1)))+(V2 % W(2)*(-CI + $ *(TMP0)+CI*(TMP1))+V3 % W(2)*(+CI*(TMP5)-CI*(TMP6)))) + V1%W(3)= DENOM*(TMP8*(-CI*(P2(2))+CI*(P3(2)))+(V2 % W(3)*(-CI + $ *(TMP0)+CI*(TMP1))+V3 % W(3)*(+CI*(TMP5)-CI*(TMP6)))) + V1%W(4)= DENOM*(TMP8*(-CI*(P2(3))+CI*(P3(3)))+(V2 % W(4)*(-CI + $ *(TMP0)+CI*(TMP1))+V3 % W(4)*(+CI*(TMP5)-CI*(TMP6)))) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/MP_VVV1_0.f b/UNITTEST_proc/Source/DHELAS/MP_VVV1_0.f new file mode 100644 index 0000000000..db92b4282c --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/MP_VVV1_0.f @@ -0,0 +1,53 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C P(3,1)*Metric(1,2) - P(3,2)*Metric(1,2) - P(2,1)*Metric(1,3) + +C P(2,3)*Metric(1,3) + P(1,2)*Metric(2,3) - P(1,3)*Metric(2,3) +C + SUBROUTINE MP_VVV1_0(V1, V2, V3, COUP,VERTEX) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*32 CI + PARAMETER (CI=(0Q0,1Q0)) + COMPLEX*32 COUP + REAL*16 P1(0:3) + REAL*16 P2(0:3) + REAL*16 P3(0:3) + COMPLEX*32 TMP0 + COMPLEX*32 TMP1 + COMPLEX*32 TMP3 + COMPLEX*32 TMP4 + COMPLEX*32 TMP5 + COMPLEX*32 TMP6 + COMPLEX*32 TMP7 + COMPLEX*32 TMP8 + COMPLEX*32 TMP9 + TYPE(MP_ALOHA) V1 + TYPE(MP_ALOHA) V2 + TYPE(MP_ALOHA) V3 + COMPLEX*32 VERTEX + P1(:) = V1 % P (:) + P2(:) = V2 % P (:) + P3(:) = V3 % P (:) + TMP0 = (V3 % W(1)*P1(0)-V3 % W(2)*P1(1)-V3 % W(3)*P1(2)-V3 % W(4) + $ *P1(3)) + TMP1 = (V3 % W(1)*P2(0)-V3 % W(2)*P2(1)-V3 % W(3)*P2(2)-V3 % W(4) + $ *P2(3)) + TMP3 = (V2 % W(1)*V1 % W(1)-V2 % W(2)*V1 % W(2)-V2 % W(3)*V1 % + $ W(3)-V2 % W(4)*V1 % W(4)) + TMP4 = (V3 % W(1)*V1 % W(1)-V3 % W(2)*V1 % W(2)-V3 % W(3)*V1 % + $ W(3)-V3 % W(4)*V1 % W(4)) + TMP5 = (V2 % W(1)*P1(0)-V2 % W(2)*P1(1)-V2 % W(3)*P1(2)-V2 % W(4) + $ *P1(3)) + TMP6 = (V2 % W(1)*P3(0)-V2 % W(2)*P3(1)-V2 % W(3)*P3(2)-V2 % W(4) + $ *P3(3)) + TMP7 = (P2(0)*V1 % W(1)-P2(1)*V1 % W(2)-P2(2)*V1 % W(3)-P2(3)*V1 + $ % W(4)) + TMP8 = (V2 % W(1)*V3 % W(1)-V2 % W(2)*V3 % W(2)-V2 % W(3)*V3 % + $ W(3)-V2 % W(4)*V3 % W(4)) + TMP9 = (P3(0)*V1 % W(1)-P3(1)*V1 % W(2)-P3(2)*V1 % W(3)-P3(3)*V1 + $ % W(4)) + VERTEX = COUP*(TMP3*(-CI*(TMP0)+CI*(TMP1))+(TMP4*(+CI*(TMP5)-CI + $ *(TMP6))+TMP8*(-CI*(TMP7)+CI*(TMP9)))) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/MP_VVVV1LP0_1.f b/UNITTEST_proc/Source/DHELAS/MP_VVVV1LP0_1.f new file mode 100644 index 0000000000..1eb5b5abd5 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/MP_VVVV1LP0_1.f @@ -0,0 +1,30 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C Metric(1,4)*Metric(2,3) - Metric(1,3)*Metric(2,4) +C + SUBROUTINE MP_VVVV1LP0_1(V2, V3, V4, COUP, M1, W1,V1) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*32 CI + PARAMETER (CI=(0Q0,1Q0)) + COMPLEX*32 COUP + REAL*16 M1 + COMPLEX*32 TMP11 + COMPLEX*32 TMP8 + TYPE(MP_ALOHA) V1 + TYPE(MP_ALOHA) V2 + TYPE(MP_ALOHA) V3 + TYPE(MP_ALOHA) V4 + REAL*16 W1 + V1%P(:) = +V2%P(:)+V3%P(:)+V4%P(:) + TMP11 = (V2 % W(1)*V4 % W(1)-V2 % W(2)*V4 % W(2)-V2 % W(3)*V4 % + $ W(3)-V2 % W(4)*V4 % W(4)) + TMP8 = (V2 % W(1)*V3 % W(1)-V2 % W(2)*V3 % W(2)-V2 % W(3)*V3 % + $ W(3)-V2 % W(4)*V3 % W(4)) + V1%W(1)= COUP*(-CI*(V4 % W(1)*TMP8)+CI*(V3 % W(1)*TMP11)) + V1%W(2)= COUP*(-CI*(V4 % W(2)*TMP8)+CI*(V3 % W(2)*TMP11)) + V1%W(3)= COUP*(-CI*(V4 % W(3)*TMP8)+CI*(V3 % W(3)*TMP11)) + V1%W(4)= COUP*(-CI*(V4 % W(4)*TMP8)+CI*(V3 % W(4)*TMP11)) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/MP_VVVV3LP0_1.f b/UNITTEST_proc/Source/DHELAS/MP_VVVV3LP0_1.f new file mode 100644 index 0000000000..9d29023cf0 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/MP_VVVV3LP0_1.f @@ -0,0 +1,30 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C Metric(1,4)*Metric(2,3) - Metric(1,2)*Metric(3,4) +C + SUBROUTINE MP_VVVV3LP0_1(V2, V3, V4, COUP, M1, W1,V1) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*32 CI + PARAMETER (CI=(0Q0,1Q0)) + COMPLEX*32 COUP + REAL*16 M1 + COMPLEX*32 TMP2 + COMPLEX*32 TMP8 + TYPE(MP_ALOHA) V1 + TYPE(MP_ALOHA) V2 + TYPE(MP_ALOHA) V3 + TYPE(MP_ALOHA) V4 + REAL*16 W1 + V1%P(:) = +V2%P(:)+V3%P(:)+V4%P(:) + TMP2 = (V3 % W(1)*V4 % W(1)-V3 % W(2)*V4 % W(2)-V3 % W(3)*V4 % + $ W(3)-V3 % W(4)*V4 % W(4)) + TMP8 = (V2 % W(1)*V3 % W(1)-V2 % W(2)*V3 % W(2)-V2 % W(3)*V3 % + $ W(3)-V2 % W(4)*V3 % W(4)) + V1%W(1)= COUP*(-CI*(V4 % W(1)*TMP8)+CI*(V2 % W(1)*TMP2)) + V1%W(2)= COUP*(-CI*(V4 % W(2)*TMP8)+CI*(V2 % W(2)*TMP2)) + V1%W(3)= COUP*(-CI*(V4 % W(3)*TMP8)+CI*(V2 % W(3)*TMP2)) + V1%W(4)= COUP*(-CI*(V4 % W(4)*TMP8)+CI*(V2 % W(4)*TMP2)) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/MP_VVVV4LP0_1.f b/UNITTEST_proc/Source/DHELAS/MP_VVVV4LP0_1.f new file mode 100644 index 0000000000..960037890a --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/MP_VVVV4LP0_1.f @@ -0,0 +1,30 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C Metric(1,3)*Metric(2,4) - Metric(1,2)*Metric(3,4) +C + SUBROUTINE MP_VVVV4LP0_1(V2, V3, V4, COUP, M1, W1,V1) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*32 CI + PARAMETER (CI=(0Q0,1Q0)) + COMPLEX*32 COUP + REAL*16 M1 + COMPLEX*32 TMP11 + COMPLEX*32 TMP2 + TYPE(MP_ALOHA) V1 + TYPE(MP_ALOHA) V2 + TYPE(MP_ALOHA) V3 + TYPE(MP_ALOHA) V4 + REAL*16 W1 + V1%P(:) = +V2%P(:)+V3%P(:)+V4%P(:) + TMP11 = (V2 % W(1)*V4 % W(1)-V2 % W(2)*V4 % W(2)-V2 % W(3)*V4 % + $ W(3)-V2 % W(4)*V4 % W(4)) + TMP2 = (V3 % W(1)*V4 % W(1)-V3 % W(2)*V4 % W(2)-V3 % W(3)*V4 % + $ W(3)-V3 % W(4)*V4 % W(4)) + V1%W(1)= COUP*(-CI*(V3 % W(1)*TMP11)+CI*(V2 % W(1)*TMP2)) + V1%W(2)= COUP*(-CI*(V3 % W(2)*TMP11)+CI*(V2 % W(2)*TMP2)) + V1%W(3)= COUP*(-CI*(V3 % W(3)*TMP11)+CI*(V2 % W(3)*TMP2)) + V1%W(4)= COUP*(-CI*(V3 % W(4)*TMP11)+CI*(V2 % W(4)*TMP2)) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/R2_GG_1_0.f b/UNITTEST_proc/Source/DHELAS/R2_GG_1_0.f new file mode 100644 index 0000000000..79ba6ed000 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/R2_GG_1_0.f @@ -0,0 +1,24 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C P(-1,1)*P(-1,1)*Metric(1,2) +C + SUBROUTINE R2_GG_1_0(V1, V2, COUP,VERTEX) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*16 CI + PARAMETER (CI=(0D0,1D0)) + COMPLEX*16 COUP + REAL*8 P1(0:3) + COMPLEX*16 TMP12 + COMPLEX*16 TMP3 + TYPE(ALOHA) V1 + TYPE(ALOHA) V2 + COMPLEX*16 VERTEX + P1(:) = V1 % P (:) + TMP12 = (P1(0)*P1(0)-P1(1)*P1(1)-P1(2)*P1(2)-P1(3)*P1(3)) + TMP3 = (V2 % W(1)*V1 % W(1)-V2 % W(2)*V1 % W(2)-V2 % W(3)*V1 % + $ W(3)-V2 % W(4)*V1 % W(4)) + VERTEX = COUP*(-CI * TMP3*TMP12) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/R2_GG_1_R2_GG_2_0.f b/UNITTEST_proc/Source/DHELAS/R2_GG_1_R2_GG_2_0.f new file mode 100644 index 0000000000..2cb5ba766e --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/R2_GG_1_R2_GG_2_0.f @@ -0,0 +1,31 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +Coup(1) * (P(-1,1)*P(-1,1)*Metric(1,2)) + Coup(2) * (P(1,1)*P(2,1)) +C + SUBROUTINE R2_GG_1_R2_GG_2_0(V1, V2, COUP1, COUP2,VERTEX) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*16 CI + PARAMETER (CI=(0D0,1D0)) + COMPLEX*16 COUP1 + COMPLEX*16 COUP2 + REAL*8 P1(0:3) + COMPLEX*16 TMP12 + COMPLEX*16 TMP13 + COMPLEX*16 TMP3 + COMPLEX*16 TMP5 + TYPE(ALOHA) V1 + TYPE(ALOHA) V2 + COMPLEX*16 VERTEX + P1(:) = V1 % P (:) + TMP12 = (P1(0)*P1(0)-P1(1)*P1(1)-P1(2)*P1(2)-P1(3)*P1(3)) + TMP13 = (P1(0)*V1 % W(1)-P1(1)*V1 % W(2)-P1(2)*V1 % W(3)-P1(3) + $ *V1 % W(4)) + TMP3 = (V2 % W(1)*V1 % W(1)-V2 % W(2)*V1 % W(2)-V2 % W(3)*V1 % + $ W(3)-V2 % W(4)*V1 % W(4)) + TMP5 = (V2 % W(1)*P1(0)-V2 % W(2)*P1(1)-V2 % W(3)*P1(2)-V2 % W(4) + $ *P1(3)) + VERTEX = (-1D0)*(+CI*(TMP3*TMP12*COUP1+TMP5*TMP13*COUP2)) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/R2_GG_1_R2_GG_3_0.f b/UNITTEST_proc/Source/DHELAS/R2_GG_1_R2_GG_3_0.f new file mode 100644 index 0000000000..b5a7aa5c89 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/R2_GG_1_R2_GG_3_0.f @@ -0,0 +1,25 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +Coup(1) * (P(-1,1)*P(-1,1)*Metric(1,2)) + Coup(2) * (Metric(1,2)) +C + SUBROUTINE R2_GG_1_R2_GG_3_0(V1, V2, COUP1, COUP2,VERTEX) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*16 CI + PARAMETER (CI=(0D0,1D0)) + COMPLEX*16 COUP1 + COMPLEX*16 COUP2 + REAL*8 P1(0:3) + COMPLEX*16 TMP12 + COMPLEX*16 TMP3 + TYPE(ALOHA) V1 + TYPE(ALOHA) V2 + COMPLEX*16 VERTEX + P1(:) = V1 % P (:) + TMP12 = (P1(0)*P1(0)-P1(1)*P1(1)-P1(2)*P1(2)-P1(3)*P1(3)) + TMP3 = (V2 % W(1)*V1 % W(1)-V2 % W(2)*V1 % W(2)-V2 % W(3)*V1 % + $ W(3)-V2 % W(4)*V1 % W(4)) + VERTEX = -TMP3*(+CI*(TMP12*COUP1+COUP2)) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/R2_GG_2_0.f b/UNITTEST_proc/Source/DHELAS/R2_GG_2_0.f new file mode 100644 index 0000000000..663bbc2cc6 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/R2_GG_2_0.f @@ -0,0 +1,25 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C P(1,1)*P(2,1) +C + SUBROUTINE R2_GG_2_0(V1, V2, COUP,VERTEX) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*16 CI + PARAMETER (CI=(0D0,1D0)) + COMPLEX*16 COUP + REAL*8 P1(0:3) + COMPLEX*16 TMP13 + COMPLEX*16 TMP5 + TYPE(ALOHA) V1 + TYPE(ALOHA) V2 + COMPLEX*16 VERTEX + P1(:) = V1 % P (:) + TMP13 = (P1(0)*V1 % W(1)-P1(1)*V1 % W(2)-P1(2)*V1 % W(3)-P1(3) + $ *V1 % W(4)) + TMP5 = (V2 % W(1)*P1(0)-V2 % W(2)*P1(1)-V2 % W(3)*P1(2)-V2 % W(4) + $ *P1(3)) + VERTEX = COUP*(-CI * TMP5*TMP13) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/R2_GG_3_0.f b/UNITTEST_proc/Source/DHELAS/R2_GG_3_0.f new file mode 100644 index 0000000000..3a3edb5bd7 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/R2_GG_3_0.f @@ -0,0 +1,20 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C Metric(1,2) +C + SUBROUTINE R2_GG_3_0(V1, V2, COUP,VERTEX) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*16 CI + PARAMETER (CI=(0D0,1D0)) + COMPLEX*16 COUP + COMPLEX*16 TMP3 + TYPE(ALOHA) V1 + TYPE(ALOHA) V2 + COMPLEX*16 VERTEX + TMP3 = (V2 % W(1)*V1 % W(1)-V2 % W(2)*V1 % W(2)-V2 % W(3)*V1 % + $ W(3)-V2 % W(4)*V1 % W(4)) + VERTEX = COUP*(-CI * TMP3) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/R2_QQ_1_0.f b/UNITTEST_proc/Source/DHELAS/R2_QQ_1_0.f new file mode 100644 index 0000000000..4be3fea115 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/R2_QQ_1_0.f @@ -0,0 +1,33 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C P(-1,1)*Gamma(-1,2,1) +C + SUBROUTINE R2_QQ_1_0(F1, F2, COUP,VERTEX) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*16 CI + PARAMETER (CI=(0D0,1D0)) + COMPLEX*16 COUP + TYPE(ALOHA) F1 + INTEGER FLV_INDEX1 + TYPE(ALOHA) F2 + INTEGER FLV_INDEX2 + REAL*8 P1(0:3) + COMPLEX*16 TMP14 + COMPLEX*16 VERTEX + P1(:) = F1 % P (:) + FLV_INDEX1 = F1 %FLV_INDEX + FLV_INDEX2 = F2 %FLV_INDEX + IF(FLV_INDEX1.NE.FLV_INDEX2.OR.FLV_INDEX1.EQ.0)THEN + VERTEX = (0D0,0D0) + RETURN + ENDIF + TMP14 = (F1 % W(1)*(F2 % W(3)*(P1(0)+P1(3))+F2 % W(4)*(P1(1)+CI + $ *(P1(2))))+(F1 % W(2)*(F2 % W(3)*(P1(1)-CI*(P1(2)))+F2 % W(4) + $ *(P1(0)-P1(3)))+(F1 % W(3)*(F2 % W(1)*(P1(0)-P1(3))-F2 % W(2) + $ *(P1(1)+CI*(P1(2))))+F1 % W(4)*(F2 % W(1)*(-P1(1)+CI*(P1(2))) + $ +F2 % W(2)*(P1(0)+P1(3)))))) + VERTEX = COUP*(-CI * TMP14) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/R2_QQ_1_R2_QQ_2_0.f b/UNITTEST_proc/Source/DHELAS/R2_QQ_1_R2_QQ_2_0.f new file mode 100644 index 0000000000..566ac0dd08 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/R2_QQ_1_R2_QQ_2_0.f @@ -0,0 +1,37 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +Coup(1) * (P(-1,1)*Gamma(-1,2,1)) + Coup(2) * (Identity(1,2)) +C + SUBROUTINE R2_QQ_1_R2_QQ_2_0(F1, F2, COUP1, COUP2,VERTEX) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*16 CI + PARAMETER (CI=(0D0,1D0)) + COMPLEX*16 COUP1 + COMPLEX*16 COUP2 + TYPE(ALOHA) F1 + INTEGER FLV_INDEX1 + TYPE(ALOHA) F2 + INTEGER FLV_INDEX2 + REAL*8 P1(0:3) + COMPLEX*16 TMP15 + COMPLEX*16 TMP16 + COMPLEX*16 VERTEX + P1(:) = F1 % P (:) + FLV_INDEX1 = F1 %FLV_INDEX + FLV_INDEX2 = F2 %FLV_INDEX + IF(FLV_INDEX1.NE.FLV_INDEX2.OR.FLV_INDEX1.EQ.0)THEN + VERTEX = (0D0,0D0) + RETURN + ENDIF + TMP15 = (F2 % W(1)*F1 % W(1)+F2 % W(2)*F1 % W(2)+F2 % W(3)*F1 % + $ W(3)+F2 % W(4)*F1 % W(4)) + TMP16 = (F1 % W(1)*(F2 % W(3)*(P1(0)+P1(3))+F2 % W(4)*(P1(1)+CI + $ *(P1(2))))+(F1 % W(2)*(F2 % W(3)*(P1(1)-CI*(P1(2)))+F2 % W(4) + $ *(P1(0)-P1(3)))+(F1 % W(3)*(F2 % W(1)*(P1(0)-P1(3))-F2 % W(2) + $ *(P1(1)+CI*(P1(2))))+F1 % W(4)*(F2 % W(1)*(-P1(1)+CI*(P1(2))) + $ +F2 % W(2)*(P1(0)+P1(3)))))) + VERTEX = (-1D0)*(+CI*(COUP1*TMP16+TMP15*COUP2)) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/R2_QQ_2_0.f b/UNITTEST_proc/Source/DHELAS/R2_QQ_2_0.f new file mode 100644 index 0000000000..07d6cd4ff1 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/R2_QQ_2_0.f @@ -0,0 +1,28 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C Identity(1,2) +C + SUBROUTINE R2_QQ_2_0(F1, F2, COUP,VERTEX) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*16 CI + PARAMETER (CI=(0D0,1D0)) + COMPLEX*16 COUP + TYPE(ALOHA) F1 + INTEGER FLV_INDEX1 + TYPE(ALOHA) F2 + INTEGER FLV_INDEX2 + COMPLEX*16 TMP15 + COMPLEX*16 VERTEX + FLV_INDEX1 = F1 %FLV_INDEX + FLV_INDEX2 = F2 %FLV_INDEX + IF(FLV_INDEX1.NE.FLV_INDEX2.OR.FLV_INDEX1.EQ.0)THEN + VERTEX = (0D0,0D0) + RETURN + ENDIF + TMP15 = (F2 % W(1)*F1 % W(1)+F2 % W(2)*F1 % W(2)+F2 % W(3)*F1 % + $ W(3)+F2 % W(4)*F1 % W(4)) + VERTEX = COUP*(-CI * TMP15) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/VVV1LP0_1.f b/UNITTEST_proc/Source/DHELAS/VVV1LP0_1.f new file mode 100644 index 0000000000..ef3a9f1d45 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/VVV1LP0_1.f @@ -0,0 +1,49 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C P(3,1)*Metric(1,2) - P(3,2)*Metric(1,2) - P(2,1)*Metric(1,3) + +C P(2,3)*Metric(1,3) + P(1,2)*Metric(2,3) - P(1,3)*Metric(2,3) +C + SUBROUTINE VVV1LP0_1(V2, V3, COUP, M1, W1,V1) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*16 CI + PARAMETER (CI=(0D0,1D0)) + COMPLEX*16 COUP + REAL*8 M1 + COMPLEX*16 P1(0:3) + COMPLEX*16 P2(0:3) + COMPLEX*16 P3(0:3) + COMPLEX*16 TMP0 + COMPLEX*16 TMP1 + COMPLEX*16 TMP5 + COMPLEX*16 TMP6 + COMPLEX*16 TMP8 + TYPE(ALOHA) V1 + TYPE(ALOHA) V2 + TYPE(ALOHA) V3 + REAL*8 W1 + P2(:) = V2 % P (:) + P3(:) = V3 % P (:) + V1%P(:) = +V2%P(:)+V3%P(:) + P1(:) = -V1 % P (:) + TMP0 = (V3 % W(1)*P1(0)-V3 % W(2)*P1(1)-V3 % W(3)*P1(2)-V3 % W(4) + $ *P1(3)) + TMP1 = (V3 % W(1)*P2(0)-V3 % W(2)*P2(1)-V3 % W(3)*P2(2)-V3 % W(4) + $ *P2(3)) + TMP5 = (V2 % W(1)*P1(0)-V2 % W(2)*P1(1)-V2 % W(3)*P1(2)-V2 % W(4) + $ *P1(3)) + TMP6 = (V2 % W(1)*P3(0)-V2 % W(2)*P3(1)-V2 % W(3)*P3(2)-V2 % W(4) + $ *P3(3)) + TMP8 = (V2 % W(1)*V3 % W(1)-V2 % W(2)*V3 % W(2)-V2 % W(3)*V3 % + $ W(3)-V2 % W(4)*V3 % W(4)) + V1%W(1)= COUP*(TMP8*(-CI*(P2(0))+CI*(P3(0)))+(V2 % W(1)*(-CI + $ *(TMP0)+CI*(TMP1))+V3 % W(1)*(+CI*(TMP5)-CI*(TMP6)))) + V1%W(2)= COUP*(TMP8*(-CI*(P2(1))+CI*(P3(1)))+(V2 % W(2)*(-CI + $ *(TMP0)+CI*(TMP1))+V3 % W(2)*(+CI*(TMP5)-CI*(TMP6)))) + V1%W(3)= COUP*(TMP8*(-CI*(P2(2))+CI*(P3(2)))+(V2 % W(3)*(-CI + $ *(TMP0)+CI*(TMP1))+V3 % W(3)*(+CI*(TMP5)-CI*(TMP6)))) + V1%W(4)= COUP*(TMP8*(-CI*(P2(3))+CI*(P3(3)))+(V2 % W(4)*(-CI + $ *(TMP0)+CI*(TMP1))+V3 % W(4)*(+CI*(TMP5)-CI*(TMP6)))) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/VVV1P0_1.f b/UNITTEST_proc/Source/DHELAS/VVV1P0_1.f new file mode 100644 index 0000000000..e45def8ee7 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/VVV1P0_1.f @@ -0,0 +1,52 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C P(3,1)*Metric(1,2) - P(3,2)*Metric(1,2) - P(2,1)*Metric(1,3) + +C P(2,3)*Metric(1,3) + P(1,2)*Metric(2,3) - P(1,3)*Metric(2,3) +C + SUBROUTINE VVV1P0_1(V2, V3, COUP, M1, W1,V1) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*16 CI + PARAMETER (CI=(0D0,1D0)) + COMPLEX*16 COUP + REAL*8 M1 + REAL*8 P1(0:3) + REAL*8 P2(0:3) + REAL*8 P3(0:3) + COMPLEX*16 TMP0 + COMPLEX*16 TMP1 + COMPLEX*16 TMP5 + COMPLEX*16 TMP6 + COMPLEX*16 TMP8 + TYPE(ALOHA) V1 + TYPE(ALOHA) V2 + TYPE(ALOHA) V3 + REAL*8 W1 + COMPLEX*16 DENOM + P2(:) = V2 % P (:) + P3(:) = V3 % P (:) + V1%P(:) = +V2%P(:)+V3%P(:) + P1(:) = -V1 % P (:) + TMP0 = (V3 % W(1)*P1(0)-V3 % W(2)*P1(1)-V3 % W(3)*P1(2)-V3 % W(4) + $ *P1(3)) + TMP1 = (V3 % W(1)*P2(0)-V3 % W(2)*P2(1)-V3 % W(3)*P2(2)-V3 % W(4) + $ *P2(3)) + TMP5 = (V2 % W(1)*P1(0)-V2 % W(2)*P1(1)-V2 % W(3)*P1(2)-V2 % W(4) + $ *P1(3)) + TMP6 = (V2 % W(1)*P3(0)-V2 % W(2)*P3(1)-V2 % W(3)*P3(2)-V2 % W(4) + $ *P3(3)) + TMP8 = (V2 % W(1)*V3 % W(1)-V2 % W(2)*V3 % W(2)-V2 % W(3)*V3 % + $ W(3)-V2 % W(4)*V3 % W(4)) + DENOM = COUP/(P1(0)**2-P1(1)**2-P1(2)**2-P1(3)**2 - M1 * (M1 -CI + $ * W1)) + V1%W(1)= DENOM*(TMP8*(-CI*(P2(0))+CI*(P3(0)))+(V2 % W(1)*(-CI + $ *(TMP0)+CI*(TMP1))+V3 % W(1)*(+CI*(TMP5)-CI*(TMP6)))) + V1%W(2)= DENOM*(TMP8*(-CI*(P2(1))+CI*(P3(1)))+(V2 % W(2)*(-CI + $ *(TMP0)+CI*(TMP1))+V3 % W(2)*(+CI*(TMP5)-CI*(TMP6)))) + V1%W(3)= DENOM*(TMP8*(-CI*(P2(2))+CI*(P3(2)))+(V2 % W(3)*(-CI + $ *(TMP0)+CI*(TMP1))+V3 % W(3)*(+CI*(TMP5)-CI*(TMP6)))) + V1%W(4)= DENOM*(TMP8*(-CI*(P2(3))+CI*(P3(3)))+(V2 % W(4)*(-CI + $ *(TMP0)+CI*(TMP1))+V3 % W(4)*(+CI*(TMP5)-CI*(TMP6)))) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/VVV1_0.f b/UNITTEST_proc/Source/DHELAS/VVV1_0.f new file mode 100644 index 0000000000..be7989d115 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/VVV1_0.f @@ -0,0 +1,53 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C P(3,1)*Metric(1,2) - P(3,2)*Metric(1,2) - P(2,1)*Metric(1,3) + +C P(2,3)*Metric(1,3) + P(1,2)*Metric(2,3) - P(1,3)*Metric(2,3) +C + SUBROUTINE VVV1_0(V1, V2, V3, COUP,VERTEX) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*16 CI + PARAMETER (CI=(0D0,1D0)) + COMPLEX*16 COUP + REAL*8 P1(0:3) + REAL*8 P2(0:3) + REAL*8 P3(0:3) + COMPLEX*16 TMP0 + COMPLEX*16 TMP1 + COMPLEX*16 TMP3 + COMPLEX*16 TMP4 + COMPLEX*16 TMP5 + COMPLEX*16 TMP6 + COMPLEX*16 TMP7 + COMPLEX*16 TMP8 + COMPLEX*16 TMP9 + TYPE(ALOHA) V1 + TYPE(ALOHA) V2 + TYPE(ALOHA) V3 + COMPLEX*16 VERTEX + P1(:) = V1 % P (:) + P2(:) = V2 % P (:) + P3(:) = V3 % P (:) + TMP0 = (V3 % W(1)*P1(0)-V3 % W(2)*P1(1)-V3 % W(3)*P1(2)-V3 % W(4) + $ *P1(3)) + TMP1 = (V3 % W(1)*P2(0)-V3 % W(2)*P2(1)-V3 % W(3)*P2(2)-V3 % W(4) + $ *P2(3)) + TMP3 = (V2 % W(1)*V1 % W(1)-V2 % W(2)*V1 % W(2)-V2 % W(3)*V1 % + $ W(3)-V2 % W(4)*V1 % W(4)) + TMP4 = (V3 % W(1)*V1 % W(1)-V3 % W(2)*V1 % W(2)-V3 % W(3)*V1 % + $ W(3)-V3 % W(4)*V1 % W(4)) + TMP5 = (V2 % W(1)*P1(0)-V2 % W(2)*P1(1)-V2 % W(3)*P1(2)-V2 % W(4) + $ *P1(3)) + TMP6 = (V2 % W(1)*P3(0)-V2 % W(2)*P3(1)-V2 % W(3)*P3(2)-V2 % W(4) + $ *P3(3)) + TMP7 = (P2(0)*V1 % W(1)-P2(1)*V1 % W(2)-P2(2)*V1 % W(3)-P2(3)*V1 + $ % W(4)) + TMP8 = (V2 % W(1)*V3 % W(1)-V2 % W(2)*V3 % W(2)-V2 % W(3)*V3 % + $ W(3)-V2 % W(4)*V3 % W(4)) + TMP9 = (P3(0)*V1 % W(1)-P3(1)*V1 % W(2)-P3(2)*V1 % W(3)-P3(3)*V1 + $ % W(4)) + VERTEX = COUP*(TMP3*(-CI*(TMP0)+CI*(TMP1))+(TMP4*(+CI*(TMP5)-CI + $ *(TMP6))+TMP8*(-CI*(TMP7)+CI*(TMP9)))) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/VVVV1LP0_1.f b/UNITTEST_proc/Source/DHELAS/VVVV1LP0_1.f new file mode 100644 index 0000000000..d8ecf01791 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/VVVV1LP0_1.f @@ -0,0 +1,30 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C Metric(1,4)*Metric(2,3) - Metric(1,3)*Metric(2,4) +C + SUBROUTINE VVVV1LP0_1(V2, V3, V4, COUP, M1, W1,V1) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*16 CI + PARAMETER (CI=(0D0,1D0)) + COMPLEX*16 COUP + REAL*8 M1 + COMPLEX*16 TMP11 + COMPLEX*16 TMP8 + TYPE(ALOHA) V1 + TYPE(ALOHA) V2 + TYPE(ALOHA) V3 + TYPE(ALOHA) V4 + REAL*8 W1 + V1%P(:) = +V2%P(:)+V3%P(:)+V4%P(:) + TMP11 = (V2 % W(1)*V4 % W(1)-V2 % W(2)*V4 % W(2)-V2 % W(3)*V4 % + $ W(3)-V2 % W(4)*V4 % W(4)) + TMP8 = (V2 % W(1)*V3 % W(1)-V2 % W(2)*V3 % W(2)-V2 % W(3)*V3 % + $ W(3)-V2 % W(4)*V3 % W(4)) + V1%W(1)= COUP*(-CI*(V4 % W(1)*TMP8)+CI*(V3 % W(1)*TMP11)) + V1%W(2)= COUP*(-CI*(V4 % W(2)*TMP8)+CI*(V3 % W(2)*TMP11)) + V1%W(3)= COUP*(-CI*(V4 % W(3)*TMP8)+CI*(V3 % W(3)*TMP11)) + V1%W(4)= COUP*(-CI*(V4 % W(4)*TMP8)+CI*(V3 % W(4)*TMP11)) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/VVVV3LP0_1.f b/UNITTEST_proc/Source/DHELAS/VVVV3LP0_1.f new file mode 100644 index 0000000000..da4463779f --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/VVVV3LP0_1.f @@ -0,0 +1,30 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C Metric(1,4)*Metric(2,3) - Metric(1,2)*Metric(3,4) +C + SUBROUTINE VVVV3LP0_1(V2, V3, V4, COUP, M1, W1,V1) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*16 CI + PARAMETER (CI=(0D0,1D0)) + COMPLEX*16 COUP + REAL*8 M1 + COMPLEX*16 TMP2 + COMPLEX*16 TMP8 + TYPE(ALOHA) V1 + TYPE(ALOHA) V2 + TYPE(ALOHA) V3 + TYPE(ALOHA) V4 + REAL*8 W1 + V1%P(:) = +V2%P(:)+V3%P(:)+V4%P(:) + TMP2 = (V3 % W(1)*V4 % W(1)-V3 % W(2)*V4 % W(2)-V3 % W(3)*V4 % + $ W(3)-V3 % W(4)*V4 % W(4)) + TMP8 = (V2 % W(1)*V3 % W(1)-V2 % W(2)*V3 % W(2)-V2 % W(3)*V3 % + $ W(3)-V2 % W(4)*V3 % W(4)) + V1%W(1)= COUP*(-CI*(V4 % W(1)*TMP8)+CI*(V2 % W(1)*TMP2)) + V1%W(2)= COUP*(-CI*(V4 % W(2)*TMP8)+CI*(V2 % W(2)*TMP2)) + V1%W(3)= COUP*(-CI*(V4 % W(3)*TMP8)+CI*(V2 % W(3)*TMP2)) + V1%W(4)= COUP*(-CI*(V4 % W(4)*TMP8)+CI*(V2 % W(4)*TMP2)) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/VVVV4LP0_1.f b/UNITTEST_proc/Source/DHELAS/VVVV4LP0_1.f new file mode 100644 index 0000000000..f8fcb8d1e8 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/VVVV4LP0_1.f @@ -0,0 +1,30 @@ +C This File is Automatically generated by ALOHA +C The process calculated in this file is: +C Metric(1,3)*Metric(2,4) - Metric(1,2)*Metric(3,4) +C + SUBROUTINE VVVV4LP0_1(V2, V3, V4, COUP, M1, W1,V1) + USE ALOHA_OBJECT + IMPLICIT NONE + COMPLEX*16 CI + PARAMETER (CI=(0D0,1D0)) + COMPLEX*16 COUP + REAL*8 M1 + COMPLEX*16 TMP11 + COMPLEX*16 TMP2 + TYPE(ALOHA) V1 + TYPE(ALOHA) V2 + TYPE(ALOHA) V3 + TYPE(ALOHA) V4 + REAL*8 W1 + V1%P(:) = +V2%P(:)+V3%P(:)+V4%P(:) + TMP11 = (V2 % W(1)*V4 % W(1)-V2 % W(2)*V4 % W(2)-V2 % W(3)*V4 % + $ W(3)-V2 % W(4)*V4 % W(4)) + TMP2 = (V3 % W(1)*V4 % W(1)-V3 % W(2)*V4 % W(2)-V3 % W(3)*V4 % + $ W(3)-V3 % W(4)*V4 % W(4)) + V1%W(1)= COUP*(-CI*(V3 % W(1)*TMP11)+CI*(V2 % W(1)*TMP2)) + V1%W(2)= COUP*(-CI*(V3 % W(2)*TMP11)+CI*(V2 % W(2)*TMP2)) + V1%W(3)= COUP*(-CI*(V3 % W(3)*TMP11)+CI*(V2 % W(3)*TMP2)) + V1%W(4)= COUP*(-CI*(V3 % W(4)*TMP11)+CI*(V2 % W(4)*TMP2)) + END + + diff --git a/UNITTEST_proc/Source/DHELAS/aloha_file.inc b/UNITTEST_proc/Source/DHELAS/aloha_file.inc new file mode 100644 index 0000000000..e62ba70b1b --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/aloha_file.inc @@ -0,0 +1 @@ +ALOHARoutine = FFV1LP0_3.o FFV1L_1.o FFV1L_2.o FFV1P0_3.o FFV1_0.o FFV1_1.o FFV1_2.o GHGHGL_1.o GHGHGL_2.o MP_FFV1LP0_3.o MP_FFV1L_1.o MP_FFV1L_2.o MP_FFV1P0_3.o MP_FFV1_0.o MP_FFV1_1.o MP_FFV1_2.o MP_GHGHGL_1.o MP_GHGHGL_2.o MP_R2_GG_1_0.o MP_R2_GG_1_R2_GG_2_0.o MP_R2_GG_1_R2_GG_3_0.o MP_R2_GG_2_0.o MP_R2_GG_3_0.o MP_R2_QQ_1_0.o MP_R2_QQ_1_R2_QQ_2_0.o MP_R2_QQ_2_0.o MP_VVV1LP0_1.o MP_VVV1P0_1.o MP_VVV1_0.o MP_VVVV1LP0_1.o MP_VVVV3LP0_1.o MP_VVVV4LP0_1.o R2_GG_1_0.o R2_GG_1_R2_GG_2_0.o R2_GG_1_R2_GG_3_0.o R2_GG_2_0.o R2_GG_3_0.o R2_QQ_1_0.o R2_QQ_1_R2_QQ_2_0.o R2_QQ_2_0.o VVV1LP0_1.o VVV1P0_1.o VVV1_0.o VVVV1LP0_1.o VVVV3LP0_1.o VVVV4LP0_1.o diff --git a/UNITTEST_proc/Source/DHELAS/aloha_functions.f b/UNITTEST_proc/Source/DHELAS/aloha_functions.f new file mode 100644 index 0000000000..46561ce7d9 --- /dev/null +++ b/UNITTEST_proc/Source/DHELAS/aloha_functions.f @@ -0,0 +1,3044 @@ +C############################################################################### +C +C Copyright (c) 2010 The ALOHA Development team and Contributors +C +C This file is a part of the MadGraph5_aMC@NLO project, an application which +C automatically generates Feynman diagrams and matrix elements for arbitrary +C high-energy processes in the Standard Model and beyond. +C +C It is subject to the ALOHA license which should accompany this +C distribution. +C +C############################################################################### + module ALOHA_OBJECT + TYPE ALOHA + SEQUENCE + double complex::W(4) + double complex :: P(0:3) + integer :: flv_index + END TYPE ALOHA + TYPE ALOHA2D + SEQUENCE + double complex::W(16) + double complex :: P(0:3) + integer :: flv_index + END TYPE ALOHA2D + TYPE MP_ALOHA + SEQUENCE + complex*32 :: W(4) + complex*32 :: P(0:3) + integer :: flv_index + END TYPE MP_ALOHA + TYPE MP_ALOHA2D + SEQUENCE + complex*32 :: W(16) + complex*32 :: P(0:3) + integer :: flv_index + END TYPE MP_ALOHA2D + end module ALOHA_OBJECT + + subroutine ixxxxx(p, fmass, nhel, nsf, flavor ,fi) +c +c This subroutine computes a fermion wavefunction with the flowing-IN +c fermion number. +c +c input: +c real p(0:3) : four-momentum of fermion +c real fmass : mass of fermion +c integer nhel = -1 or 1 : helicity of fermion +c integer nsf = -1 or 1 : +1 for particle, -1 for anti-particle +c +c output: +c type(aloha) fi : fermion wavefunction |fi> +c + use ALOHA_OBJECT + implicit none + type(aloha) fi + double complex chi(2) + double precision p(0:3),sf(2),sfomeg(2),omega(2),fmass, + & pp,pp3,sqp0p3,sqm(0:1) + integer nhel,nsf,ip,im,nh,flavor + + double precision rZero, rHalf, rTwo + parameter( rZero = 0.0d0, rHalf = 0.5d0, rTwo = 2.0d0 ) + +c#ifdef HELAS_CHECK +c double precision p2 +c double precision epsi +c parameter( epsi = 2.0d-5 ) +c integer stdo +c parameter( stdo = 6 ) +c#endif +c +c#ifdef HELAS_CHECK +c pp = sqrt(p(1)**2+p(2)**2+p(3)**2) +c if ( abs(p(0))+pp.eq.rZero ) then +c write(stdo,*) +c & ' helas-error : p(0:3) in ixxxxx is zero momentum' +c endif +c if ( p(0).le.rZero ) then +c write(stdo,*) +c & ' helas-error : p(0:3) in ixxxxx has non-positive energy' +c write(stdo,*) +c & ' : p(0) = ',p(0) +c endif +c p2 = (p(0)-pp)*(p(0)+pp) +c if ( abs(p2-fmass**2).gt.p(0)**2*epsi ) then +c write(stdo,*) +c & ' helas-error : p(0:3) in ixxxxx has inappropriate mass' +c write(stdo,*) +c & ' : p**2 = ',p2,' : fmass**2 = ',fmass**2 +c endif +c if (abs(nhel).ne.1) then +c write(stdo,*) ' helas-error : nhel in ixxxxx is not -1,1' +c write(stdo,*) ' : nhel = ',nhel +c endif +c if (abs(nsf).ne.1) then +c write(stdo,*) ' helas-error : nsf in ixxxxx is not -1,1' +c write(stdo,*) ' : nsf = ',nsf +c endif +c#endif + +c Convention for trees +c fi(5) = dcmplx(p(0),p(3))*nsf +c fi(6) = dcmplx(p(1),p(2))*nsf + +c Convention for loop computations + fi%P(0) = p(0)*(-nsf) + fi%P(1) = p(1)*(-nsf) + fi%P(2) = p(2)*(-nsf) + fi%P(3) = p(3)*(-nsf) + fi%flv_index = flavor + + nh = nhel*nsf + + if ( fmass.ne.rZero ) then + + pp = min(p(0),dsqrt(p(1)**2+p(2)**2+p(3)**2)) + + + if ( pp.eq.rZero ) then + + sqm(0) = dsqrt(abs(fmass)) ! possibility of negative fermion masses + sqm(1) = sign(sqm(0),fmass) ! possibility of negative fermion masses + ip = (1+nh)/2 + im = (1-nh)/2 + + fi%W(1) = ip * sqm(ip) + fi%W(2) = im*nsf * sqm(ip) + fi%W(3) = ip*nsf * sqm(im) + fi%W(4) = im * sqm(im) + + else + + sf(1) = dble(1+nsf+(1-nsf)*nh)*rHalf + sf(2) = dble(1+nsf-(1-nsf)*nh)*rHalf + omega(1) = dsqrt(p(0)+pp) + omega(2) = fmass/omega(1) + ip = (3+nh)/2 + im = (3-nh)/2 + sfomeg(1) = sf(1)*omega(ip) + sfomeg(2) = sf(2)*omega(im) + pp3 = max(pp+p(3),rZero) + chi(1) = dcmplx( dsqrt(pp3*rHalf/pp) ) + if ( pp3.eq.rZero ) then + chi(2) = dcmplx(-nh ) + else + chi(2) = dcmplx( nh*p(1) , p(2) )/dsqrt(rTwo*pp*pp3) + endif + + fi%W(1) = sfomeg(1)*chi(im) + fi%W(2) = sfomeg(1)*chi(ip) + fi%W(3) = sfomeg(2)*chi(im) + fi%W(4) = sfomeg(2)*chi(ip) + + endif + + else + + if(p(1).eq.0d0.and.p(2).eq.0d0.and.p(3).lt.0d0) then + sqp0p3 = 0d0 + else + sqp0p3 = dsqrt(max(p(0)+p(3),rZero))*nsf + end if + chi(1) = dcmplx( sqp0p3 ) + if ( sqp0p3.eq.rZero ) then + chi(2) = dcmplx(-nhel )*dsqrt(rTwo*p(0)) + else + chi(2) = dcmplx( nh*p(1), p(2) )/sqp0p3 + endif + if ( nh.eq.1 ) then + fi%W(1) = dcmplx( rZero ) + fi%W(2) = dcmplx( rZero ) + fi%W(3) = chi(1) + fi%W(4) = chi(2) + else + fi%W(1) = chi(2) + fi%W(2) = chi(1) + fi%W(3) = dcmplx( rZero ) + fi%W(4) = dcmplx( rZero ) + endif + endif +c + return + end + + + subroutine ixxxso(p, fmass, nhel, nsf, flavor ,fi) +c +c This subroutine computes a fermion wavefunction with the flowing-IN +c fermion number. +c +c input: +c real p(0:3) : four-momentum of fermion +c real fmass : mass of fermion +c integer nhel = -1 or 1 : helicity of fermion +c integer nsf = -1 or 1 : +1 for particle, -1 for anti-particle +c +c output: +c type(aloha) fi : fermion wavefunction |fi> +c + use ALOHA_OBJECT + implicit none + type(aloha) fi + double complex chi(2) + double precision p(0:3),sf(2),sfomeg(2),omega(2),fmass, + & pp,pp3,sqp0p3,sqm(0:1) + integer nhel,nsf,ip,im,nh,flavor + + double precision rZero, rHalf, rTwo + parameter( rZero = 0.0d0, rHalf = 0.5d0, rTwo = 2.0d0 ) + +c#ifdef HELAS_CHECK +c double precision p2 +c double precision epsi +c parameter( epsi = 2.0d-5 ) +c integer stdo +c parameter( stdo = 6 ) +c#endif +c +c#ifdef HELAS_CHECK +c pp = sqrt(p(1)**2+p(2)**2+p(3)**2) +c if ( abs(p(0))+pp.eq.rZero ) then +c write(stdo,*) +c & ' helas-error : p(0:3) in ixxxxx is zero momentum' +c endif +c if ( p(0).le.rZero ) then +c write(stdo,*) +c & ' helas-error : p(0:3) in ixxxxx has non-positive energy' +c write(stdo,*) +c & ' : p(0) = ',p(0) +c endif +c p2 = (p(0)-pp)*(p(0)+pp) +c if ( abs(p2-fmass**2).gt.p(0)**2*epsi ) then +c write(stdo,*) +c & ' helas-error : p(0:3) in ixxxxx has inappropriate mass' +c write(stdo,*) +c & ' : p**2 = ',p2,' : fmass**2 = ',fmass**2 +c endif +c if (abs(nhel).ne.1) then +c write(stdo,*) ' helas-error : nhel in ixxxxx is not -1,1' +c write(stdo,*) ' : nhel = ',nhel +c endif +c if (abs(nsf).ne.1) then +c write(stdo,*) ' helas-error : nsf in ixxxxx is not -1,1' +c write(stdo,*) ' : nsf = ',nsf +c endif +c#endif + +c Convention for trees +c fi(5) = dcmplx(p(0),p(3))*nsf +c fi(6) = dcmplx(p(1),p(2))*nsf + +c$$$c Convention for loop computations +c$$$ fi(1) = dcmplx(p(0),0.D0)*(-nsf) +c$$$ fi(2) = dcmplx(p(1),0.D0)*(-nsf) +c$$$ fi(3) = dcmplx(p(2),0.D0)*(-nsf) +c$$$ fi(4) = dcmplx(p(3),0.D0)*(-nsf) + + fi%P(0) = p(0)*(-nsf) + fi%P(1) = p(1)*(-nsf) + fi%P(2) = p(2)*(-nsf) + fi%P(3) = p(3)*(-nsf) + fi%flv_index = flavor + + nh = nhel*nsf + + if ( fmass.ne.rZero ) then + + pp = min(p(0),dsqrt(p(1)**2+p(2)**2+p(3)**2)) + + if ( pp.eq.rZero ) then + + sqm(0) = dsqrt(abs(fmass)) ! possibility of negative fermion masses + sqm(1) = sign(sqm(0),fmass) ! possibility of negative fermion masses + ip = (1+nh)/2 + im = (1-nh)/2 + + fi%W(1) = ip * sqm(ip) + fi%W(2) = im*nsf * sqm(ip) + fi%W(3) = ip*nsf * sqm(im) + fi%W(4) = im * sqm(im) + + else + + sf(1) = dble(1+nsf+(1-nsf)*nh)*rHalf + sf(2) = dble(1+nsf-(1-nsf)*nh)*rHalf + omega(1) = dsqrt(p(0)+pp) + omega(2) = fmass/omega(1) + ip = (3+nh)/2 + im = (3-nh)/2 + sfomeg(1) = sf(1)*omega(ip) + sfomeg(2) = sf(2)*omega(im) + pp3 = max(pp+p(3),rZero) + chi(1) = dcmplx( dsqrt(pp3*rHalf/pp) ) + if ( pp3.eq.rZero ) then + chi(2) = dcmplx(-nh ) + else + chi(2) = dcmplx( nh*p(1) , p(2) )/dsqrt(rTwo*pp*pp3) + endif + + fi%W(1) = sfomeg(1)*chi(im) + fi%W(2) = sfomeg(1)*chi(ip) + fi%W(3) = sfomeg(2)*chi(im) + fi%W(4) = sfomeg(2)*chi(ip) + + endif + + else + + if(p(1).eq.0d0.and.p(2).eq.0d0.and.p(3).lt.0d0) then + sqp0p3 = 0d0 + else + sqp0p3 = dsqrt(max(p(0)+p(3),rZero))*nsf + end if + chi(1) = dcmplx( sqp0p3 ) + if ( sqp0p3.eq.rZero ) then + chi(2) = dcmplx(-nhel )*dsqrt(rTwo*p(0)) + else + chi(2) = dcmplx( nh*p(1), p(2) )/sqp0p3 + endif + if ( nh.eq.1 ) then + fi%W(1) = dcmplx( rZero ) + fi%W(2) = dcmplx( rZero ) + fi%W(3) = chi(1) + fi%W(4) = chi(2) + else + fi%W(1) = chi(2) + fi%W(2) = chi(1) + fi%W(3) = dcmplx( rZero ) + fi%W(4) = dcmplx( rZero ) + endif + endif +c + return + end + + + subroutine mp_ixxxxx(p, fmass, nhel, nsf, flavor ,fi) +c +c This subroutine computes a fermion wavefunction with the flowing-IN +c fermion number, in QUADRUPLE PRECISIOn +c +c input: +c real p(0:3) : four-momentum of fermion +c real fmass : mass of fermion +c integer nhel = -1 or 1 : helicity of fermion +c integer nsf = -1 or 1 : +1 for particle, -1 for anti-particle +c +c output: +c type(mp_aloha) fi : fermion wavefunction |fi> +c + use ALOHA_OBJECT + implicit none + type(mp_aloha) fi + complex*32 chi(2) + real*16 p(0:3),sf(2),sfomeg(2),omega(2),fmass, + & pp,pp3,sqp0p3,sqm(0:1) + integer nhel,nsf,ip,im,nh,flavor + + real*16 rZero, rHalf, rTwo + parameter( rZero = 0.0e0_16, rHalf = 0.5e0_16, rTwo = 2.0e0_16 ) +c Convention for loop computations + fi%P(0) = p(0)*(-nsf) + fi%P(1) = p(1)*(-nsf) + fi%P(2) = p(2)*(-nsf) + fi%P(3) = p(3)*(-nsf) + fi%flv_index = flavor + + nh = nhel*nsf + + if ( fmass.ne.rZero ) then + + pp = min(p(0),sqrt(p(1)**2+p(2)**2+p(3)**2)) + + if ( pp.eq.rZero ) then + + sqm(0) = sqrt(abs(fmass)) ! possibility of negative fermion masses + sqm(1) = sign(sqm(0),fmass) ! possibility of negative fermion masses + ip = (1+nh)/2 + im = (1-nh)/2 + + fi%W(1) = ip * sqm(ip) + fi%W(2) = im*nsf * sqm(ip) + fi%W(3) = ip*nsf * sqm(im) + fi%W(4) = im * sqm(im) + + else + + sf(1) = REAL(1+nsf+(1-nsf)*nh,KIND=16)*rHalf + sf(2) = REAL(1+nsf-(1-nsf)*nh,KIND=16)*rHalf + omega(1) = sqrt(p(0)+pp) + omega(2) = fmass/omega(1) + ip = (3+nh)/2 + im = (3-nh)/2 + sfomeg(1) = sf(1)*omega(ip) + sfomeg(2) = sf(2)*omega(im) + pp3 = max(pp+p(3),rZero) + chi(1) = cmplx( sqrt(pp3*rHalf/pp), KIND=16 ) + if ( pp3.eq.rZero ) then + chi(2) = cmplx(-nh ,KIND=16) + else + chi(2) = cmplx( nh*p(1) , p(2),KIND=16)/sqrt(rTwo*pp*pp3) + endif + + fi%W(1) = sfomeg(1)*chi(im) + fi%W(2) = sfomeg(1)*chi(ip) + fi%W(3) = sfomeg(2)*chi(im) + fi%W(4) = sfomeg(2)*chi(ip) + + endif + + else + + if(p(1).eq.0d0.and.p(2).eq.0d0.and.p(3).lt.0d0) then + sqp0p3 = 0d0 + else + sqp0p3 = sqrt(max(p(0)+p(3),rZero))*nsf + end if + chi(1) = cmplx( sqp0p3 ,KIND=16) + if ( sqp0p3.eq.rZero ) then + chi(2) = cmplx(-nhel ,KIND=16)*sqrt(rTwo*p(0)) + else + chi(2) = cmplx( nh*p(1), p(2) ,KIND=16)/sqp0p3 + endif + if ( nh.eq.1 ) then + fi%W(1) = cmplx( rZero ,KIND=16) + fi%W(2) = cmplx( rZero ,KIND=16) + fi%W(3) = chi(1) + fi%W(4) = chi(2) + else + fi%W(1) = chi(2) + fi%W(2) = chi(1) + fi%W(3) = cmplx( rZero ,KIND=16) + fi%W(4) = cmplx( rZero ,KIND=16) + endif + endif +c + return + end + + subroutine oxxxxx(p,fmass,nhel,nsf, flavor , fo) +c +c This subroutine computes a fermion wavefunction with the flowing-OUT +c fermion number. +c +c input: +c real p(0:3) : four-momentum of fermion +c real fmass : mass of fermion +c integer nhel = -1 or 1 : helicity of fermion +c integer nsf = -1 or 1 : +1 for particle, -1 for anti-particle +c +c output: +c type(aloha) fo : fermion wavefunction +c Note: There are 4 components for the spinor and four for the +c momentum. + implicit none + double complex fi(8),chi(2), fmass +c double precision p(0:3),sf(2),sfomeg(2),omega(2),fmass, +c & pp,pp3,sqp0p3,sqm(0:1) + double complex sqm(0:1) + double precision sf(2),ffmass + double complex p(0:3), sfomeg(2),omega(2), + & pp,pp3,sqp0p3 + integer nhel,nsf,ip,im,nh + + double precision rZero, rHalf, rTwo + parameter( rZero = 0.0d0, rHalf = 0.5d0, rTwo = 2.0d0 ) + + + +c fi(5) = dcmplx(p(0),p(3))*nsf +c fi(6) = dcmplx(p(1),p(2))*nsf + fi(5) = p(0)*nsf + fi(6) = p(1)*nsf + fi(7) = p(2)*nsf + fi(8) = p(3)*nsf + + nh = nhel*nsf + + fmass = sqrt(p(0)**2-p(1)**2-p(2)**2-p(3)**2) + + if ( ffmass.ne.rZero ) then +c special treatment for massless particles. +c pp = min(p(0),sqrt(p(1)**2+p(2)**2+p(3)**2)) + pp=sqrt(p(1)**2+p(2)**2+p(3)**2) +c for time-like four-momenta we can always think of it as the p_vec^2 + if ( abs(pp).eq.rZero ) then +c particle at rest. + sqm(0) = sqrt(fmass) ! possibility of negative fermion masses + sqm(1) = sqm(0) ! possibility of negative fermion masses + ip = (1+nh)/2 + im = (1-nh)/2 + + fi(1) = ip * sqm(ip) + fi(2) = im*nsf * sqm(ip) + fi(3) = ip*nsf * sqm(im) + fi(4) = im * sqm(im) + + else +c standard spinor + + pp=sqrt(p(1)**2+p(2)**2+p(3)**2) + write(*,*) 'ppre=',pp +c if( (dble(p(0)) .lt. 0 .and. dble(pp) .gt. 0) .or. +c & (dble(p(0)) .lt. 0 .and. dble(pp) .gt. 0) ) then +c pp=-pp +c endif + sf(1) = dble(1+nsf+(1-nsf)*nh)*rHalf +c fermion spin using HELAS conventions. + sf(2) = dble(1+nsf-(1-nsf)*nh)*rHalf + omega(1) = sqrt(p(0)+pp) +c the omega of the definition. +c omega(2) = fmass/omega(1) + omega(2) = sqrt(p(0)-pp) +c the prefactor + ip = (3+nh)/2 + im = (3-nh)/2 + sfomeg(1) = sf(1)*omega(ip) + sfomeg(2) = sf(2)*omega(im) +c pp3 = max(pp+p(3),rZero) + pp3=pp+p(3) + chi(1) = sqrt(pp3*rHalf/pp) + if ( abs(pp3).eq.rZero ) then + chi(2) = dcmplx(-nh ) + else + chi(2) = ( (nh*p(1)) + ((0d0,1d0)*p(2)) )/ + .sqrt(rTwo*pp*pp3) + endif + + +c Write(*,*) 'Chi=',Chi(1),' and ',Chi(2) + + fi(1) = sfomeg(1)*chi(im) + fi(2) = sfomeg(1)*chi(ip) +c Write(*,*) 'fi(2)=',fi(2) + fi(3) = sfomeg(2)*chi(im) +c Write(*,*) 'fi(3)=',fi(3) + fi(4) = sfomeg(2)*chi(ip) + + endif + + else + +c if(zabs(p(1)).eq.0d0.and.zabs(p(2)).eq.0d0.and. +c .zabs(p(3)).lt.0d0) then +c sqp0p3 = 0d0 +c else + sqp0p3 = sqrt(p(0)+p(3))*nsf +c end if + chi(1) = sqp0p3 + if ( abs(sqp0p3).eq.rZero ) then + chi(2) = dcmplx(-nhel )*sqrt(rTwo*p(0)) + else + chi(2) = ( nh*p(1) + ((0d0,1d0)*p(2) ) )/sqp0p3 + endif + if ( nh.eq.1 ) then + fi(1) = dcmplx( rZero ) + fi(2) = dcmplx( rZero ) + fi(3) = chi(1) + fi(4) = chi(2) + else + fi(1) = chi(2) + fi(2) = chi(1) + fi(3) = dcmplx( rZero ) + fi(4) = dcmplx( rZero ) + endif + endif + + return + end + + subroutine olxxxx(p,ffmass,nhel,nsf,fo) +c +c This subroutine computes a fermion wavefunction with the flowing-OUT +c fermion number and defined with complex ONSHELL momentum. +c +c input: +c complex p(0:3) : four-momentum of fermion +c real fmass : mass of fermion +c integer nhel = -1 or 1 : helicity of fermion +c integer nsf = -1 or 1 : +1 for particle, -1 for anti-particle +c +c output: +c complex fo(8) : fermion wavefunction islatin=true if letter is a latin letter +c ++ +c +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + subroutine LHA_islatin(letter,islatin) + implicit none + + logical islatin + character letter + integer i + + islatin=.false. + i=ichar(letter) + if(i.ge.65.and.i.le. 90) islatin=.true. + if(i.ge.97.and.i.le.122) islatin=.true. + + end + +c +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +c ++ +c ++ LHA_isnum -> isnum=true if letter is a number +c ++ +c +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + subroutine LHA_isnum(letter,isnum) + implicit none + + logical isnum + character letter + character*10 ref + integer i + + isnum=.false. + ref='1234567890' + + do i=1,10 + if(letter .eq. ref(i:i)) isnum=.true. + end do + + end + +c +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +c ++ +c ++ LHA_firststring -> first is the first "word" of string +c ++ Warning: string is returned with first REMOVED! +c ++ +c +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + subroutine LHA_firststring(first,string) + + implicit none + character*(*) string + character*(*) first + + if(len_trim(string).le.0) return + + do while(string(1:1) .eq. ' ') + string=string(2:len(string)) + end do + if (index(string,' ').gt.1) then + first=string(1:index(string,' ')-1) + string=string(index(string,' '):len(string)) + else + first=string + end if + + end + + + subroutine LHA_case_trap(name) +c +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +c ++ +c ++ LHA_case_trap -> change string to lower case +c ++ +c +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + implicit none + + character*20 name + integer i,k + + do i=1,20 + k=ichar(name(i:i)) + if(k.ge.65.and.k.le.90) then !upper case A-Z + k=ichar(name(i:i))+32 + name(i:i)=char(k) + endif + enddo + + return + end + +c +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +c ++ +c ++ LHA_blockread -> read a LHA line and return parameter name (evntually found in +c ++ a ref file) and value +c ++ +c +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + subroutine LHA_blockread(blockname,buff,par,val,found) + + implicit none + character*132 buff,buffer,curr_ref,curr_buff + character*20 blockname,val,par,temp,first_ref,first_line + logical fopened + integer ref_file + logical islast,isnum,found + character*20 temp_val + + logical isBlank + integer i + character(512) IdentCardPath + + character(512) ParamCardPath + data ParamCardPath/'.'/ + common/ParamCardPath/ParamCardPath + +c ********************************************************************* +c Try to find a correspondance in ident_card +c + + IdentCardPath='' + i =1 + isBlank = .False. + do while (i.le.LEN(ParamCardPath) .and. + \ .not. isBlank) + if (ParamCardPath(i:i).eq.' ') then + isBlank=.True. + else + i=i+1 + endif + enddo + IdentCardPath = ParamCardPath(1:i-1)//'/ident_card.dat' + ref_file = 20 + call LHA_open_file(ref_file,IdentCardPath,fopened) + if(.not. fopened) goto 99 ! If the file does not exist -> no matter, use default! + + islast=.false. + found=.false. + do while(.not. found)!run over reference file + + + ! read a line + read(ref_file,'(a132)',end=98,err=98) buffer + + ! Seek a corresponding blockname + call LHA_firststring(temp,buffer) + call LHA_case_trap(temp) + + if(temp .eq. blockname) then + ! Seek for a corresponding LHA code + curr_ref=buffer + curr_buff=buff + first_ref='' + first_line='' + + do while((.not. islast).and.(first_ref .eq. first_line)) + call LHA_firststring(first_ref,curr_ref) + call LHA_firststring(first_line,curr_buff) + call LHA_islatin(first_ref(1:1),islast) + if (islast) then + par=first_ref + val=first_line ! If found set param name & value + found=.true. + end if + end do + end if + + end do +98 close(ref_file) +99 return + end + + +c +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +c ++ +c ++ LHA_loadcard -> Open a LHA file and load all model param in a table +c ++ +c +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + subroutine LHA_loadcard(param_name,npara,param,value) + + implicit none + + integer maxpara + parameter (maxpara=1000) + character*20 param(maxpara),value(maxpara),val,par + character*20 blockname + integer npara + logical fopened,found + integer iunit,GL,logfile + character*20 ctemp + character*132 buff + character*20 tag + character*132 temp + character*(*) param_name + data iunit/21/ + data logfile/22/ + + logical WriteParamLog + common/IOcontrol/WriteParamLog + + GL=0 + npara=1 + + param(1)=' ' + value(1)=' ' + + ! Try to open param-card file + call LHA_open_file(iunit,param_name,fopened) + if(.not.fopened) then + write(*,*) 'Error: Could not open file',param_name + write(*,*) 'Exiting' + stop + endif + + ! Try to open log file + if (WriteParamLog) then + open (unit = logfile, file = "param.log") + endif + + ! Scan the data file + do while(.true.) + + read(iunit,'(a132)',end=99,err=99) buff + + if(buff .ne. '' .and. buff(1:1) .ne.'#') then ! Skip comments and empty lines + + tag=buff(1:5) + call LHA_case_trap(tag) ! Select decay/block tag + if(tag .eq. 'block') then ! If we are in a block, get the blockname + temp=buff(7:132) + call LHA_firststring(blockname,temp) + call LHA_case_trap(blockname) + else if (tag .eq. 'decay') then ! If we are in a decay, directly try to get back the correct name/value pair + blockname='decay' + temp=buff(7:132) + call LHA_blockread(blockname,temp,par,val,found) + if(found) GL=1 + else if ((tag .eq. 'qnumbers').or.(blockname.eq.'')) then! if qnumbers or empty tag do nothing + blockname='' + else ! If we are in valid block, try to get back a name/value pair + call LHA_blockread(blockname,buff,par,val,found) + if(found) GL=1 + end if + + !if LHA_blockread has been called, record name and value + + if(GL .eq. 1) then + value(npara)=val + ctemp=par + call LHA_case_trap(ctemp) + param(npara)=ctemp + npara=npara+1 + GL=0 + if (WriteParamLog) then + write (logfile,*) 'Parameter ',ctemp, + & ' has been read with value ',val + endif + endif + + endif + enddo + + npara=npara-1 + 99 close(iunit) + if (WriteParamLog) then + close(logfile) + endif + + return + + end + + + + subroutine LHA_get_real_silent(npara,param,value,name,var,def_value_num) +c---------------------------------------------------------------------------------- +c finds the parameter named "name" in param and associate to "value" in value +c---------------------------------------------------------------------------------- + implicit none + +c +c parameters +c + integer maxpara + parameter (maxpara=1000) +c +c arguments +c + integer npara + character*20 param(maxpara),value(maxpara) + character*(*) name + real*8 var,def_value_num + character*20 c_param,c_name,ctemp + character*19 def_value +c +c local +c + logical found, log + integer i +c +c start +c + log = .false. + goto 10 + + entry LHA_get_real(npara,param,value,name,var,def_value_num) + log = .true. + + 10 i=1 + found=.false. + do while(.not.found.and.i.le.npara) + ctemp=param(i) + call LHA_firststring(c_param,ctemp) + ctemp=name + call LHA_firststring(c_name,ctemp) + call LHA_case_trap(c_name) + call LHA_case_trap(c_param) + found = (c_param .eq. c_name) + if (found) then + read(value(i),*) var + end if + i=i+1 + enddo + if (.not.found) then + if (log) then + write (*,*) "Warning: parameter ",name," not found" + write (*,*) " setting it to default value ", + & def_value_num + endif + var=def_value_num + endif + return + + end +c + + + subroutine MP_LHA_get_real_silent(npara,param,value,name,var, + &def_value_num) +c---------------------------------------------------------------------------------- +c finds the parameter named "name" in param and associate to "value" in value +c---------------------------------------------------------------------------------- + implicit none + +c +c parameters +c + integer maxpara + parameter (maxpara=1000) +c +c arguments +c + integer npara + character*20 param(maxpara),value(maxpara) + character*(*) name + real*16 var,def_value_num + real*8 buff + character*20 c_param,c_name,ctemp + character*19 def_value +c +c local +c + logical found, log + integer i +c +c start +c + log = .false. + goto 10 + entry MP_LHA_get_real(npara,param,value,name,var, + & def_value_num) + log = .true. + + 10 i=1 + found=.false. + do while(.not.found.and.i.le.npara) + ctemp=param(i) + call LHA_firststring(c_param,ctemp) + ctemp=name + call LHA_firststring(c_name,ctemp) + call LHA_case_trap(c_name) + call LHA_case_trap(c_param) + found = (c_param .eq. c_name) + if (found) then + read(value(i),*) buff + var=buff + end if + i=i+1 + enddo + if (.not.found) then + if (log) then + buff = def_value_num + write (*,*) "Warning: parameter ",name," not found" + write (*,*) " setting it to default value ", + & buff + endif + var=def_value_num + endif + return + + end +c + + + + subroutine LHA_open_file(lun,filename,fopened) +c*********************************************************************** +c opens file input-card.dat in current directory or above +c*********************************************************************** + implicit none +c +c Arguments +c + integer lun + logical fopened + character*(*) filename + character*512 tempname + integer fine + integer dirup,i + + character(512) ParamCardPath + common/ParamCardPath/ParamCardPath + +c----- +c Begin Code +c----- +c +c first check that we will end in the main directory +c + ! Somehow it seems important to make sure the flow is + ! iunit is closed before opening it. + close(lun) + open(unit=lun,file=filename,status='old',ERR=20) +c write(*,*) 'read model file ',filename + fopened=.true. + if (filename(len(trim(filename))-13:len(trim(filename))).eq."param_card.dat") then + ParamCardPath = filename(1:len(trim(filename))-15) + endif + return + +20 tempname=filename + fine=index(tempname,' ') + if(fine.eq.0) fine=len(tempname) + tempname=tempname(1:fine) +c +c if I have to read a card +c + if(index(filename,"_card").gt.0) then + tempname='./Cards/'//tempname + endif + + fopened=.false. + do i=0,5 + open(unit=lun,file=tempname,status='old',ERR=30) + fopened=.true. +c write(*,*) 'read model file ',tempname + exit +30 tempname='../'//tempname + if (i.eq.5)then + write(*,*) 'Warning: file ',filename, + & ' not found in the parent directories!(not found for mp_)' + stop + endif + enddo + + return + end + diff --git a/UNITTEST_proc/Source/MODEL/makefile b/UNITTEST_proc/Source/MODEL/makefile new file mode 100644 index 0000000000..1275410de2 --- /dev/null +++ b/UNITTEST_proc/Source/MODEL/makefile @@ -0,0 +1,56 @@ +# ---------------------------------------------------------------------------- +# +# Makefile for model library +# +# ---------------------------------------------------------------------------- + +# Check for ../make_opts +ifeq ($(wildcard ../make_opts), ../make_opts) + include ../make_opts + FFLAGS+= -fPIC +else + FFLAGS+= -fPIC -ffixed-line-length-132 + FC=gfortran +endif + +include makeinc.inc + +LIBDIR=../../lib/ +LIBRARY=libmodel.$(libext) +LIBRARY_SHARED=libmodel.$(dylibext) + +all: $(LIBDIR)$(LIBRARY) + +helas_couplings: helas_couplings.o $(LIBRARY) + $(FC) $(FFLAGS) -o $@ $^ + +testprog: testprog.o $(LIBRARY) + $(FC) $(FFLAGS) -o $@ $^ + +$(LIBRARY): $(MODEL) + ar cru $(LIBRARY) $(MODEL) + ranlib $(LIBRARY) + +$(LIBDIR)$(LIBRARY): $(MODEL) + $(call CREATELIB, $@, $^) + +$(LIBDIR)$(LIBRARY_SHARED): $(MODEL) + $(FC) -shared -o $@ $^ $(LDFLAGS) + +shared: $(LIBDIR)$(LIBRARY_SHARED) +clean: + $(RM) *.o $(LIBDIR)$(LIBRARY) + +couplings.o: ../maxparticles.inc ../run.inc ../cuts.inc + +../maxparticles.inc: + touch ../maxparticles.inc + +../run.inc: + touch ../run.inc + +../cuts.inc: + echo " logical fixed_extra_scale" > ../cuts.inc + echo " integer maxjetflavor" >> ../cuts.inc + echo " double precision mue_ref_fixed, mue_over_ref" >> ../cuts.inc + diff --git a/UNITTEST_proc/Source/MODEL/makeinc.inc b/UNITTEST_proc/Source/MODEL/makeinc.inc new file mode 100644 index 0000000000..699348c3ac --- /dev/null +++ b/UNITTEST_proc/Source/MODEL/makeinc.inc @@ -0,0 +1,5 @@ +############################################################################# +# written by the UFO converter +############################################################################# + +MODEL = flavor_couplings.o couplings.o lha_read.o printout.o rw_para.o model_functions.o get_color.o couplings1.o couplings2.o couplings3.o mp_couplings1.o mp_couplings2.o mp_couplings3.o \ No newline at end of file diff --git a/UNITTEST_proc/Source/MODEL/model_functions.f b/UNITTEST_proc/Source/MODEL/model_functions.f new file mode 100644 index 0000000000..0a5f1443ac --- /dev/null +++ b/UNITTEST_proc/Source/MODEL/model_functions.f @@ -0,0 +1,1038 @@ +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +c written by the UFO converter +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc + + DOUBLE COMPLEX FUNCTION COND(CONDITION,TRUECASE,FALSECASE) + IMPLICIT NONE + DOUBLE COMPLEX CONDITION,TRUECASE,FALSECASE + IF(CONDITION.EQ.(0.0D0,0.0D0)) THEN + COND=TRUECASE + ELSE + COND=FALSECASE + ENDIF + END + + DOUBLE COMPLEX FUNCTION CONDIF(CONDITION,TRUECASE,FALSECASE) + IMPLICIT NONE + LOGICAL CONDITION + DOUBLE COMPLEX TRUECASE,FALSECASE + IF(CONDITION) THEN + CONDIF=TRUECASE + ELSE + CONDIF=FALSECASE + ENDIF + END + + DOUBLE COMPLEX FUNCTION RECMS(CONDITION,EXPR) + IMPLICIT NONE + LOGICAL CONDITION + DOUBLE COMPLEX EXPR + IF(CONDITION)THEN + RECMS=EXPR + ELSE + RECMS=DCMPLX(DBLE(EXPR)) + ENDIF + END + + DOUBLE COMPLEX FUNCTION REGLOG(ARG_IN) + IMPLICIT NONE + DOUBLE COMPLEX TWOPII + PARAMETER (TWOPII=2.0D0*3.1415926535897932D0*(0.0D0,1.0D0)) + DOUBLE COMPLEX ARG_IN + DOUBLE COMPLEX ARG + ARG=ARG_IN + IF(DABS(DIMAG(ARG)).EQ.0.0D0)THEN + ARG=DCMPLX(DBLE(ARG),0.0D0) + ENDIF + IF(DABS(DBLE(ARG)).EQ.0.0D0)THEN + ARG=DCMPLX(0.0D0,DIMAG(ARG)) + ENDIF + IF(ARG.EQ.(0.0D0,0.0D0)) THEN + REGLOG=(0.0D0,0.0D0) + ELSE + REGLOG=LOG(ARG) + ENDIF + END + + DOUBLE COMPLEX FUNCTION REGLOGP(ARG_IN) + IMPLICIT NONE + DOUBLE COMPLEX TWOPII + PARAMETER (TWOPII=2.0D0*3.1415926535897932D0*(0.0D0,1.0D0)) + DOUBLE COMPLEX ARG_IN + DOUBLE COMPLEX ARG + ARG=ARG_IN + IF(DABS(DIMAG(ARG)).EQ.0.0D0)THEN + ARG=DCMPLX(DBLE(ARG),0.0D0) + ENDIF + IF(DABS(DBLE(ARG)).EQ.0.0D0)THEN + ARG=DCMPLX(0.0D0,DIMAG(ARG)) + ENDIF + IF(ARG.EQ.(0.0D0,0.0D0))THEN + REGLOGP=(0.0D0,0.0D0) + ELSE + IF(DBLE(ARG).LT.0.0D0.AND.DIMAG(ARG).LT.0.0D0)THEN + REGLOGP=LOG(ARG) + TWOPII + ELSE + REGLOGP=LOG(ARG) + ENDIF + ENDIF + END + + DOUBLE COMPLEX FUNCTION REGLOGM(ARG_IN) + IMPLICIT NONE + DOUBLE COMPLEX TWOPII + PARAMETER (TWOPII=2.0D0*3.1415926535897932D0*(0.0D0,1.0D0)) + DOUBLE COMPLEX ARG_IN + DOUBLE COMPLEX ARG + ARG=ARG_IN + IF(DABS(DIMAG(ARG)).EQ.0.0D0)THEN + ARG=DCMPLX(DBLE(ARG),0.0D0) + ENDIF + IF(DABS(DBLE(ARG)).EQ.0.0D0)THEN + ARG=DCMPLX(0.0D0,DIMAG(ARG)) + ENDIF + IF(ARG.EQ.(0.0D0,0.0D0))THEN + REGLOGM=(0.0D0,0.0D0) + ELSE + IF(DBLE(ARG).LT.0.0D0.AND.DIMAG(ARG).GT.0.0D0)THEN + REGLOGM=LOG(ARG) - TWOPII + ELSE + REGLOGM=LOG(ARG) + ENDIF + ENDIF + END + + DOUBLE COMPLEX FUNCTION REGSQRT(ARG_IN) + IMPLICIT NONE + DOUBLE COMPLEX ARG_IN + DOUBLE COMPLEX ARG + ARG=ARG_IN + IF(DABS(DIMAG(ARG)).EQ.0.0D0)THEN + ARG=DCMPLX(DBLE(ARG),0.0D0) + ENDIF + IF(DABS(DBLE(ARG)).EQ.0.0D0)THEN + ARG=DCMPLX(0.0D0,DIMAG(ARG)) + ENDIF + REGSQRT=SQRT(ARG) + END + + DOUBLE COMPLEX FUNCTION GRREGLOG(LOGSW,EXPR1_IN,EXPR2_IN) + IMPLICIT NONE + DOUBLE COMPLEX TWOPII + PARAMETER (TWOPII=2.0D0*3.1415926535897932D0*(0.0D0,1.0D0)) + DOUBLE COMPLEX EXPR1_IN,EXPR2_IN + DOUBLE COMPLEX EXPR1,EXPR2 + DOUBLE PRECISION LOGSW + DOUBLE PRECISION IMAGEXPR + LOGICAL FIRSTSHEET + EXPR1=EXPR1_IN + EXPR2=EXPR2_IN + IF(DABS(DIMAG(EXPR1)).EQ.0.0D0)THEN + EXPR1=DCMPLX(DBLE(EXPR1),0.0D0) + ENDIF + IF(DABS(DBLE(EXPR1)).EQ.0.0D0)THEN + EXPR1=DCMPLX(0.0D0,DIMAG(EXPR1)) + ENDIF + IF(DABS(DIMAG(EXPR2)).EQ.0.0D0)THEN + EXPR2=DCMPLX(DBLE(EXPR2),0.0D0) + ENDIF + IF(DABS(DBLE(EXPR2)).EQ.0.0D0)THEN + EXPR2=DCMPLX(0.0D0,DIMAG(EXPR2)) + ENDIF + IF(EXPR1.EQ.(0.0D0,0.0D0))THEN + GRREGLOG=(0.0D0,0.0D0) + ELSE + IMAGEXPR=DIMAG(EXPR1)*DIMAG(EXPR2) + FIRSTSHEET=IMAGEXPR.GE.0.0D0 + FIRSTSHEET=FIRSTSHEET.OR.DBLE(EXPR1).GE.0.0D0 + FIRSTSHEET=FIRSTSHEET.OR.DBLE(EXPR2).GE.0.0D0 + IF(FIRSTSHEET)THEN + GRREGLOG=LOG(EXPR1) + ELSE + IF(DIMAG(EXPR1).GT.0.0D0)THEN + GRREGLOG=LOG(EXPR1) - LOGSW*TWOPII + ELSE + GRREGLOG=LOG(EXPR1) + LOGSW*TWOPII + ENDIF + ENDIF + ENDIF + END + + MODULE B0F_CACHING + + TYPE B0F_NODE + DOUBLE COMPLEX P2,M12,M22 + DOUBLE COMPLEX VALUE + TYPE(B0F_NODE),POINTER::PARENT + TYPE(B0F_NODE),POINTER::LEFT + TYPE(B0F_NODE),POINTER::RIGHT + END TYPE B0F_NODE + + CONTAINS + + SUBROUTINE B0F_SEARCH(ITEM, HEAD, FIND) + IMPLICIT NONE + TYPE(B0F_NODE),POINTER,INTENT(INOUT)::HEAD,ITEM + LOGICAL,INTENT(OUT)::FIND + TYPE(B0F_NODE),POINTER::ITEM1 + INTEGER::ICOMP + FIND=.FALSE. + NULLIFY(ITEM%PARENT) + NULLIFY(ITEM%LEFT) + NULLIFY(ITEM%RIGHT) + IF(.NOT.ASSOCIATED(HEAD))THEN + HEAD => ITEM + RETURN + ENDIF + ITEM1 => HEAD + DO + ICOMP=B0F_NODE_COMPARE(ITEM,ITEM1) + IF(ICOMP.LT.0)THEN + IF(.NOT.ASSOCIATED(ITEM1%LEFT))THEN + ITEM1%LEFT => ITEM + ITEM%PARENT => ITEM1 + EXIT + ELSE + ITEM1 => ITEM1%LEFT + ENDIF + ELSEIF(ICOMP.GT.0)THEN + IF(.NOT.ASSOCIATED(ITEM1%RIGHT))THEN + ITEM1%RIGHT => ITEM + ITEM%PARENT => ITEM1 + EXIT + ELSE + ITEM1 => ITEM1%RIGHT + ENDIF + ELSE + FIND=.TRUE. + ITEM%VALUE=ITEM1%VALUE + EXIT + ENDIF + ENDDO + RETURN + END + + INTEGER FUNCTION B0F_NODE_COMPARE(ITEM1,ITEM2) RESULT(RES) + IMPLICIT NONE + TYPE(B0F_NODE),POINTER,INTENT(IN)::ITEM1,ITEM2 + RES=COMPLEX_COMPARE(ITEM1%P2,ITEM2%P2) + IF(RES.NE.0)RETURN + RES=COMPLEX_COMPARE(ITEM1%M22,ITEM2%M22) + IF(RES.NE.0)RETURN + RES=COMPLEX_COMPARE(ITEM1%M12,ITEM2%M12) + RETURN + END + + INTEGER FUNCTION REAL_COMPARE(R1,R2) RESULT(RES) + IMPLICIT NONE + DOUBLE PRECISION R1,R2 + DOUBLE PRECISION MAXR,DIFF + DOUBLE PRECISION TINY + PARAMETER (TINY=-1D-14) + MAXR=MAX(ABS(R1),ABS(R2)) + DIFF=R1-R2 + IF(MAXR.LE.1D-99.OR.ABS(DIFF)/MAX(MAXR,1D-99).LE.ABS(TINY))THEN + RES=0 + RETURN + ENDIF + IF(DIFF.GT.0D0)THEN + RES=1 + RETURN + ELSE + RES=-1 + RETURN + ENDIF + END + + INTEGER FUNCTION COMPLEX_COMPARE(C1,C2) RESULT(RES) + IMPLICIT NONE + DOUBLE COMPLEX C1,C2 + DOUBLE PRECISION R1,R2 + R1=DBLE(C1) + R2=DBLE(C2) + RES=REAL_COMPARE(R1,R2) + IF(RES.NE.0)RETURN + R1=DIMAG(C1) + R2=DIMAG(C2) + RES=REAL_COMPARE(R1,R2) + RETURN + END + + END MODULE B0F_CACHING + + DOUBLE COMPLEX FUNCTION B0F(P2,M12,M22) + USE B0F_CACHING + IMPLICIT NONE + DOUBLE COMPLEX P2,M12,M22 + DOUBLE COMPLEX ZERO,TWOPII + PARAMETER (ZERO=(0.0D0,0.0D0)) + PARAMETER (TWOPII=2.0D0*3.1415926535897932D0*(0.0D0,1.0D0)) + DOUBLE PRECISION M,M2,GA,GA2 + DOUBLE PRECISION TINY + PARAMETER (TINY=-1D-14) + DOUBLE COMPLEX LOGTERMS + DOUBLE COMPLEX LOG_TRAJECTORY + LOGICAL USE_CACHING + PARAMETER (USE_CACHING=.TRUE.) + TYPE(B0F_NODE),POINTER::ITEM + TYPE(B0F_NODE),POINTER,SAVE::B0F_BT + INTEGER INIT + SAVE INIT + DATA INIT /0/ + LOGICAL FIND + IF(M12.EQ.ZERO)THEN +C it is a special case +C refer to Eq.(5.48) in arXiv:1804.10017 + M=DBLE(P2) ! M^2 + M2=DBLE(M22) ! M2^2 + IF(M.LT.TINY.OR.M2.LT.TINY)THEN + WRITE(*,*)'ERROR:B0F is not well defined when M^2,M2^2<0' + STOP + ENDIF + M=DSQRT(DABS(M)) + M2=DSQRT(DABS(M2)) + IF(M.EQ.0D0)THEN + GA=0D0 + ELSE + GA=-DIMAG(P2)/M + ENDIF + IF(M2.EQ.0D0)THEN + GA2=0D0 + ELSE + GA2=-DIMAG(M22)/M2 + ENDIF + IF(P2.NE.M22.AND.P2.NE.ZERO.AND.M22.NE.ZERO)THEN + B0F=(M22-P2)/P2*LOG((M22-P2)/M22) + IF(M.GT.M2.AND.GA*M2.GT.GA2*M)THEN + B0F=B0F-TWOPII + ENDIF + RETURN + ELSE + WRITE(*,*)'ERROR:B0F is not supported for a simple form' + STOP + ENDIF + ENDIF +C the general case +C trajectory method as advocated in arXiv:1804.10017 (Eq.(E.47)) + IF(USE_CACHING)THEN + IF(INIT.EQ.0)THEN + NULLIFY(B0F_BT) + INIT=1 + ENDIF + ALLOCATE(ITEM) + ITEM%P2=P2 + ITEM%M12=M12 + ITEM%M22=M22 + FIND=.FALSE. + CALL B0F_SEARCH(ITEM,B0F_BT,FIND) + IF(FIND)THEN + B0F=ITEM%VALUE + DEALLOCATE(ITEM) + RETURN + ELSE + LOGTERMS=LOG_TRAJECTORY(100,P2,M12,M22) + B0F=-LOG(P2/M22)+LOGTERMS + ITEM%VALUE=B0F + RETURN + ENDIF + ELSE + LOGTERMS=LOG_TRAJECTORY(100,P2,M12,M22) + B0F=-LOG(P2/M22)+LOGTERMS + ENDIF + RETURN + END + + DOUBLE COMPLEX FUNCTION SQRT_TRAJECTORY(N_SEG,P2,M12,M22) +C only needed when p2*m12*m22=\=0 + IMPLICIT NONE + INTEGER N_SEG ! number of segments + DOUBLE COMPLEX P2,M12,M22 + DOUBLE COMPLEX ZERO,ONE + PARAMETER (ZERO=(0.0D0,0.0D0),ONE=(1.0D0,0.0D0)) + DOUBLE COMPLEX GAMMA0,GAMMA1 + DOUBLE PRECISION M,GA,DGA,GA_START + DOUBLE PRECISION GAI,INTERSECTION + DOUBLE COMPLEX ARGIM1,ARGI,P2I + DOUBLE COMPLEX GAMMA0I,GAMMA1I + DOUBLE PRECISION TINY + PARAMETER (TINY=-1D-24) + INTEGER I + DOUBLE PRECISION PREFACTOR + IF(ABS(P2*M12*M22).EQ.0D0)THEN + WRITE(*,*)'ERROR:sqrt_trajectory works when p2*m12*m22/=0' + STOP + ENDIF + M=DBLE(P2) ! M^2 + M=DSQRT(DABS(M)) + IF(M.EQ.0D0)THEN + GA=0D0 + ELSE + GA=-DIMAG(P2)/M + ENDIF +C Eq.(5.37) in arXiv:1804.10017 + GAMMA0=ONE+M12/P2-M22/P2 + GAMMA1=M12/P2-DCMPLX(0D0,1D0)*ABS(TINY)/P2 + IF(ABS(GA).EQ.0D0)THEN + SQRT_TRAJECTORY=SQRT(GAMMA0**2-4D0*GAMMA1) + RETURN + ENDIF +C segments from -DABS(tiny*Ga) to Ga + GA_START=-DABS(TINY*GA) + DGA=(GA-GA_START)/N_SEG + PREFACTOR=1D0 + GAI=GA_START + P2I=DCMPLX(M**2,-GAI*M) + GAMMA0I=ONE+M12/P2I-M22/P2I + GAMMA1I=M12/P2I-DCMPLX(0D0,1D0)*ABS(TINY)/P2I + ARGIM1=GAMMA0I**2-4D0*GAMMA1I + DO I=1,N_SEG + GAI=DGA*I+GA_START + P2I=DCMPLX(M**2,-GAI*M) + GAMMA0I=ONE+M12/P2I-M22/P2I + GAMMA1I=M12/P2I-DCMPLX(0D0,1D0)*ABS(TINY)/P2I + ARGI=GAMMA0I**2-4D0*GAMMA1I + IF(DIMAG(ARGI)*DIMAG(ARGIM1).LT.0D0)THEN + INTERSECTION=DIMAG(ARGIM1)*(DBLE(ARGI)-DBLE(ARGIM1)) + INTERSECTION=INTERSECTION/(DIMAG(ARGI)-DIMAG(ARGIM1)) + INTERSECTION=INTERSECTION-DBLE(ARGIM1) + IF(INTERSECTION.GT.0D0)THEN + PREFACTOR=-PREFACTOR + ENDIF + ENDIF + ARGIM1=ARGI + ENDDO + SQRT_TRAJECTORY=SQRT(GAMMA0**2-4D0*GAMMA1)*PREFACTOR + RETURN + END + + DOUBLE COMPLEX FUNCTION LOG_TRAJECTORY(N_SEG,P2,M12,M22) +C sum of log terms appearing in Eq.(5.35) of arXiv:1804.10017 +C only needed when p2*m12*m22=\=0 + IMPLICIT NONE +C 4 possible logarithms appearing in Eq.(5.35) of +C arXiv:1804.10017 +C log(arg(i)) with arg(i) for i=1 to 4 +C i=1: (ga_{+}-1) +C i=2: (ga_{-}-1) +C i=3: (ga_{+}-1)/ga_{+} +C i=4: (ga_{-}-1)/ga_{-} + INTEGER N_SEG ! number of segments + DOUBLE COMPLEX P2,M12,M22 + DOUBLE COMPLEX ZERO,ONE,HALF,TWOPII + PARAMETER (ZERO=(0.0D0,0.0D0),ONE=(1.0D0,0.0D0)) + PARAMETER (HALF=(0.5D0,0.0D0)) + PARAMETER (TWOPII=2.0D0*3.1415926535897932D0*(0.0D0,1.0D0)) + DOUBLE COMPLEX GAMMA0,GAMMAP,GAMMAM,SQRTTERM + DOUBLE PRECISION M,GA,DGA,GA_START + DOUBLE PRECISION GAI,INTERSECTION + DOUBLE COMPLEX ARGIM1(4),ARGI(4),P2I,SQRTTERMI + DOUBLE COMPLEX GAMMA0I,GAMMAPI,GAMMAMI + DOUBLE PRECISION TINY + PARAMETER (TINY=-1D-14) + INTEGER I,J + DOUBLE COMPLEX ADDFACTOR(4) + DOUBLE COMPLEX SQRT_TRAJECTORY + IF(ABS(P2*M12*M22).EQ.0D0)THEN + WRITE(*,*)'ERROR:log_trajectory works when p2*m12*m22/=0' + STOP + ENDIF + M=DBLE(P2) ! M^2 + M=DSQRT(DABS(M)) + IF(M.EQ.0D0)THEN + GA=0D0 + ELSE + GA=-DIMAG(P2)/M + ENDIF +C Eq.(5.36-5.38) in arXiv:1804.10017 + SQRTTERM=SQRT_TRAJECTORY(N_SEG,P2,M12,M22) + GAMMA0=ONE+M12/P2-M22/P2 + GAMMAP=HALF*(GAMMA0+SQRTTERM) + GAMMAM=HALF*(GAMMA0-SQRTTERM) + IF(ABS(GA).EQ.0D0)THEN + LOG_TRAJECTORY=-LOG(GAMMAP-ONE)-LOG(GAMMAM-ONE)+GAMMAP + $ *LOG((GAMMAP-ONE)/GAMMAP)+GAMMAM*LOG((GAMMAM-ONE)/GAMMAM) + RETURN + ENDIF +C segments from -DABS(tiny*Ga) to Ga + GA_START=-DABS(TINY*GA) + DGA=(GA-GA_START)/N_SEG + ADDFACTOR(1:4)=ZERO + GAI=GA_START + P2I=DCMPLX(M**2,-GAI*M) + SQRTTERMI=SQRT_TRAJECTORY(N_SEG,P2I,M12,M22) + GAMMA0I=ONE+M12/P2I-M22/P2I + GAMMAPI=HALF*(GAMMA0I+SQRTTERMI) + GAMMAMI=HALF*(GAMMA0I-SQRTTERMI) + ARGIM1(1)=GAMMAPI-ONE + ARGIM1(2)=GAMMAMI-ONE + ARGIM1(3)=(GAMMAPI-ONE)/GAMMAPI + ARGIM1(4)=(GAMMAMI-ONE)/GAMMAMI + DO I=1,N_SEG + GAI=DGA*I+GA_START + P2I=DCMPLX(M**2,-GAI*M) + SQRTTERMI=SQRT_TRAJECTORY(N_SEG,P2I,M12,M22) + GAMMA0I=ONE+M12/P2I-M22/P2I + GAMMAPI=HALF*(GAMMA0I+SQRTTERMI) + GAMMAMI=HALF*(GAMMA0I-SQRTTERMI) + ARGI(1)=GAMMAPI-ONE + ARGI(2)=GAMMAMI-ONE + ARGI(3)=(GAMMAPI-ONE)/GAMMAPI + ARGI(4)=(GAMMAMI-ONE)/GAMMAMI + DO J=1,4 + IF(DIMAG(ARGI(J))*DIMAG(ARGIM1(J)).LT.0D0)THEN + INTERSECTION=DIMAG(ARGIM1(J))*(DBLE(ARGI(J)) + $ -DBLE(ARGIM1(J))) + INTERSECTION=INTERSECTION/(DIMAG(ARGI(J))-DIMAG(ARGIM1(J) + $ )) + INTERSECTION=INTERSECTION-DBLE(ARGIM1(J)) + IF(INTERSECTION.GT.0D0)THEN + IF(DIMAG(ARGIM1(J)).LT.0)THEN + ADDFACTOR(J)=ADDFACTOR(J)-TWOPII + ELSE + ADDFACTOR(J)=ADDFACTOR(J)+TWOPII + ENDIF + ENDIF + ENDIF + ARGIM1(J)=ARGI(J) + ENDDO + ENDDO + LOG_TRAJECTORY=-(LOG(GAMMAP-ONE)+ADDFACTOR(1))-(LOG(GAMMAM-ONE) + $ +ADDFACTOR(2)) + LOG_TRAJECTORY=LOG_TRAJECTORY+GAMMAP*(LOG((GAMMAP-ONE)/GAMMAP) + $ +ADDFACTOR(3)) + LOG_TRAJECTORY=LOG_TRAJECTORY+GAMMAM*(LOG((GAMMAM-ONE)/GAMMAM) + $ +ADDFACTOR(4)) + RETURN + END + + DOUBLE COMPLEX FUNCTION ARG(COMNUM) + IMPLICIT NONE + DOUBLE COMPLEX COMNUM + DOUBLE COMPLEX IIM + IIM = (0.0D0,1.0D0) + IF(COMNUM.EQ.(0.0D0,0.0D0)) THEN + ARG=(0.0D0,0.0D0) + ELSE + ARG=LOG(COMNUM/ABS(COMNUM))/IIM + ENDIF + END + + + COMPLEX*32 FUNCTION MP_COND(CONDITION,TRUECASE,FALSECASE) + IMPLICIT NONE + COMPLEX*32 CONDITION,TRUECASE,FALSECASE + IF(CONDITION.EQ.(0.0E0_16,0.0E0_16)) THEN + MP_COND=TRUECASE + ELSE + MP_COND=FALSECASE + ENDIF + END + + COMPLEX*32 FUNCTION MP_CONDIF(CONDITION,TRUECASE,FALSECASE) + IMPLICIT NONE + LOGICAL CONDITION + COMPLEX*32 TRUECASE,FALSECASE + IF(CONDITION) THEN + MP_CONDIF=TRUECASE + ELSE + MP_CONDIF=FALSECASE + ENDIF + END + + COMPLEX*32 FUNCTION MP_RECMS(CONDITION,EXPR) + IMPLICIT NONE + LOGICAL CONDITION + COMPLEX*32 EXPR + IF(CONDITION)THEN + MP_RECMS=EXPR + ELSE + MP_RECMS=CMPLX(REAL(EXPR),KIND=16) + ENDIF + END + + + COMPLEX*32 FUNCTION MP_REGLOG(ARG_IN) + IMPLICIT NONE + COMPLEX*32 TWOPII + PARAMETER (TWOPII=2.0E0_16 + $ *3.14169258478796109557151794433593750E0_16*(0.0E0_16 + $ ,1.0E0_16)) + COMPLEX*32 ARG_IN + COMPLEX*32 ARG + ARG=ARG_IN + IF(ABS(IMAGPART(ARG)).EQ.0.0E0_16)THEN + ARG=CMPLX(REAL(ARG,KIND=16),0.0E0_16) + ENDIF + IF(ABS(REAL(ARG,KIND=16)).EQ.0.0E0_16)THEN + ARG=CMPLX(0.0E0_16,IMAGPART(ARG)) + ENDIF + IF(ARG.EQ.(0.0E0_16,0.0E0_16)) THEN + MP_REGLOG=(0.0E0_16,0.0E0_16) + ELSE + MP_REGLOG=LOG(ARG) + ENDIF + END + + COMPLEX*32 FUNCTION MP_REGLOGP(ARG_IN) + IMPLICIT NONE + COMPLEX*32 TWOPII + PARAMETER (TWOPII=2.0E0_16 + $ *3.14169258478796109557151794433593750E0_16*(0.0E0_16 + $ ,1.0E0_16)) + COMPLEX*32 ARG_IN + COMPLEX*32 ARG + ARG=ARG_IN + IF(ABS(IMAGPART(ARG)).EQ.0.0E0_16)THEN + ARG=CMPLX(REAL(ARG,KIND=16),0.0E0_16) + ENDIF + IF(ABS(REAL(ARG,KIND=16)).EQ.0.0E0_16)THEN + ARG=CMPLX(0.0E0_16,IMAGPART(ARG)) + ENDIF + IF(ARG.EQ.(0.0E0_16,0.0E0_16))THEN + MP_REGLOGP=(0.0E0_16,0.0E0_16) + ELSE + IF(REAL(ARG,KIND=16).LT.0.0E0_16.AND.IMAGPART(ARG) + $ .LT.0.0E0_16)THEN + MP_REGLOGP=LOG(ARG) + TWOPII + ELSE + MP_REGLOGP=LOG(ARG) + ENDIF + ENDIF + END + + COMPLEX*32 FUNCTION MP_REGLOGM(ARG_IN) + IMPLICIT NONE + COMPLEX*32 TWOPII + PARAMETER (TWOPII=2.0E0_16 + $ *3.14169258478796109557151794433593750E0_16*(0.0E0_16 + $ ,1.0E0_16)) + COMPLEX*32 ARG_IN + COMPLEX*32 ARG + ARG=ARG_IN + IF(ABS(IMAGPART(ARG)).EQ.0.0E0_16)THEN + ARG=CMPLX(REAL(ARG,KIND=16),0.0E0_16) + ENDIF + IF(ABS(REAL(ARG,KIND=16)).EQ.0.0E0_16)THEN + ARG=CMPLX(0.0E0_16,IMAGPART(ARG)) + ENDIF + IF(ARG.EQ.(0.0E0_16,0.0E0_16))THEN + MP_REGLOGM=(0.0E0_16,0.0E0_16) + ELSE + IF(REAL(ARG,KIND=16).LT.0.0E0_16.AND.IMAGPART(ARG) + $ .GT.0.0E0_16)THEN + MP_REGLOGM=LOG(ARG) - TWOPII + ELSE + MP_REGLOGM=LOG(ARG) + ENDIF + ENDIF + END + + COMPLEX*32 FUNCTION MP_REGSQRT(ARG_IN) + IMPLICIT NONE + COMPLEX*32 ARG_IN + COMPLEX*32 ARG + ARG=ARG_IN + IF(ABS(IMAGPART(ARG)).EQ.0.0E0_16)THEN + ARG=CMPLX(REAL(ARG,KIND=16),0.0E0_16) + ENDIF + IF(ABS(REAL(ARG,KIND=16)).EQ.0.0E0_16)THEN + ARG=CMPLX(0.0E0_16,IMAGPART(ARG)) + ENDIF + MP_REGSQRT=SQRT(ARG) + END + + COMPLEX*32 FUNCTION MP_GRREGLOG(LOGSW,EXPR1_IN,EXPR2_IN) + IMPLICIT NONE + COMPLEX*32 TWOPII + PARAMETER (TWOPII=2.0E0_16 + $ *3.14169258478796109557151794433593750E0_16*(0.0E0_16 + $ ,1.0E0_16)) + COMPLEX*32 EXPR1_IN,EXPR2_IN + COMPLEX*32 EXPR1,EXPR2 + REAL*16 LOGSW + REAL*16 IMAGEXPR + LOGICAL FIRSTSHEET + EXPR1=EXPR1_IN + EXPR2=EXPR2_IN + IF(ABS(IMAGPART(EXPR1)).EQ.0.0E0_16)THEN + EXPR1=CMPLX(REAL(EXPR1,KIND=16),0.0E0_16) + ENDIF + IF(ABS(REAL(EXPR1,KIND=16)).EQ.0.0E0_16)THEN + EXPR1=CMPLX(0.0E0_16,IMAGPART(EXPR1)) + ENDIF + IF(ABS(IMAGPART(EXPR2)).EQ.0.0E0_16)THEN + EXPR2=CMPLX(REAL(EXPR2,KIND=16),0.0E0_16) + ENDIF + IF(ABS(REAL(EXPR2,KIND=16)).EQ.0.0E0_16)THEN + EXPR2=CMPLX(0.0E0_16,IMAGPART(EXPR2)) + ENDIF + IF(EXPR1.EQ.(0.0E0_16,0.0E0_16))THEN + MP_GRREGLOG=(0.0E0_16,0.0E0_16) + ELSE + IMAGEXPR=IMAGPART(EXPR1)*IMAGPART(EXPR2) + FIRSTSHEET=IMAGEXPR.GE.0.0E0_16 + FIRSTSHEET=FIRSTSHEET.OR.REAL(EXPR1,KIND=16).GE.0.0E0_16 + FIRSTSHEET=FIRSTSHEET.OR.REAL(EXPR2,KIND=16).GE.0.0E0_16 + IF(FIRSTSHEET)THEN + MP_GRREGLOG=LOG(EXPR1) + ELSE + IF(IMAGPART(EXPR1).GT.0.0E0_16)THEN + MP_GRREGLOG=LOG(EXPR1) - LOGSW*TWOPII + ELSE + MP_GRREGLOG=LOG(EXPR1) + LOGSW*TWOPII + ENDIF + ENDIF + ENDIF + END + + MODULE MP_B0F_CACHING + + TYPE MP_B0F_NODE + COMPLEX*32 P2,M12,M22 + COMPLEX*32 VALUE + TYPE(MP_B0F_NODE),POINTER::PARENT + TYPE(MP_B0F_NODE),POINTER::LEFT + TYPE(MP_B0F_NODE),POINTER::RIGHT + END TYPE MP_B0F_NODE + + CONTAINS + + SUBROUTINE MP_B0F_SEARCH(ITEM, HEAD, FIND) + IMPLICIT NONE + TYPE(MP_B0F_NODE),POINTER,INTENT(INOUT)::HEAD,ITEM + LOGICAL,INTENT(OUT)::FIND + TYPE(MP_B0F_NODE),POINTER::ITEM1 + INTEGER::ICOMP + FIND=.FALSE. + NULLIFY(ITEM%PARENT) + NULLIFY(ITEM%LEFT) + NULLIFY(ITEM%RIGHT) + IF(.NOT.ASSOCIATED(HEAD))THEN + HEAD => ITEM + RETURN + ENDIF + ITEM1 => HEAD + DO + ICOMP=MP_B0F_NODE_COMPARE(ITEM,ITEM1) + IF(ICOMP.LT.0)THEN + IF(.NOT.ASSOCIATED(ITEM1%LEFT))THEN + ITEM1%LEFT => ITEM + ITEM%PARENT => ITEM1 + EXIT + ELSE + ITEM1 => ITEM1%LEFT + ENDIF + ELSEIF(ICOMP.GT.0)THEN + IF(.NOT.ASSOCIATED(ITEM1%RIGHT))THEN + ITEM1%RIGHT => ITEM + ITEM%PARENT => ITEM1 + EXIT + ELSE + ITEM1 => ITEM1%RIGHT + ENDIF + ELSE + FIND=.TRUE. + ITEM%VALUE=ITEM1%VALUE + EXIT + ENDIF + ENDDO + RETURN + END + + INTEGER FUNCTION MP_B0F_NODE_COMPARE(ITEM1,ITEM2) RESULT(RES) + IMPLICIT NONE + TYPE(MP_B0F_NODE),POINTER,INTENT(IN)::ITEM1,ITEM2 + RES=MP_COMPLEX_COMPARE(ITEM1%P2,ITEM2%P2) + IF(RES.NE.0)RETURN + RES=MP_COMPLEX_COMPARE(ITEM1%M22,ITEM2%M22) + IF(RES.NE.0)RETURN + RES=MP_COMPLEX_COMPARE(ITEM1%M12,ITEM2%M12) + RETURN + END + + INTEGER FUNCTION MP_REAL_COMPARE(R1,R2) RESULT(RES) + IMPLICIT NONE + REAL*16 R1,R2 + REAL*16 MAXR,DIFF + REAL*16 TINY + PARAMETER (TINY=-1.0E-14_16) + MAXR=MAX(ABS(R1),ABS(R2)) + DIFF=R1-R2 + IF(MAXR.LE.1.0E-99_16.OR.ABS(DIFF)/MAX(MAXR,1.0E-99_16) + $ .LE.ABS(TINY))THEN + RES=0 + RETURN + ENDIF + IF(DIFF.GT.0.0E0_16)THEN + RES=1 + RETURN + ELSE + RES=-1 + RETURN + ENDIF + END + + INTEGER FUNCTION MP_COMPLEX_COMPARE(C1,C2) RESULT(RES) + IMPLICIT NONE + COMPLEX*32 C1,C2 + REAL*16 R1,R2 + R1=REAL(C1,KIND=16) + R2=REAL(C2,KIND=16) + RES=MP_REAL_COMPARE(R1,R2) + IF(RES.NE.0)RETURN + R1=IMAGPART(C1) + R2=IMAGPART(C2) + RES=MP_REAL_COMPARE(R1,R2) + RETURN + END + + END MODULE MP_B0F_CACHING + + COMPLEX*32 FUNCTION MP_B0F(P2,M12,M22) + USE MP_B0F_CACHING + IMPLICIT NONE + COMPLEX*32 P2,M12,M22 + COMPLEX*32 ZERO,TWOPII + PARAMETER (ZERO=(0.0E0_16,0.0E0_16)) + PARAMETER (TWOPII=2.0E0_16 + $ *3.14169258478796109557151794433593750E0_16*(0.0E0_16 + $ ,1.0E0_16)) + REAL*16 M,M2,GA,GA2 + REAL*16 TINY + PARAMETER (TINY=-1.0E-14_16) + COMPLEX*32 LOGTERMS + COMPLEX*32 MP_LOG_TRAJECTORY + LOGICAL USE_CACHING + PARAMETER (USE_CACHING=.TRUE.) + TYPE(MP_B0F_NODE),POINTER::ITEM + TYPE(MP_B0F_NODE),POINTER,SAVE::B0F_BT + INTEGER INIT + SAVE INIT + DATA INIT /0/ + LOGICAL FIND + IF(M12.EQ.ZERO)THEN + M=REAL(P2,KIND=16) + M2=REAL(M22,KIND=16) + IF(M.LT.TINY.OR.M2.LT.TINY)THEN + WRITE(*,*)'ERROR:MP_B0F is not well defined when M^2' + $ //',M2^2<0' + STOP + ENDIF + M=SQRT(ABS(M)) + M2=SQRT(ABS(M2)) + IF(M.EQ.0.0E0_16)THEN + GA=0.0E0_16 + ELSE + GA=-IMAGPART(P2)/M + ENDIF + IF(M2.EQ.0.0E0_16)THEN + GA2=0.0E0_16 + ELSE + GA2=-IMAGPART(M22)/M2 + ENDIF + IF(P2.NE.M22.AND.P2.NE.ZERO.AND.M22.NE.ZERO)THEN + MP_B0F=(M22-P2)/P2*LOG((M22-P2)/M22) + IF(M.GT.M2.AND.GA*M2.GT.GA2*M)THEN + MP_B0F=MP_B0F-TWOPII + ENDIF + RETURN + ELSE + WRITE(*,*)'ERROR:MP_B0F is not supported for a simple' + $ //' form' + STOP + ENDIF + ENDIF + IF(USE_CACHING)THEN + IF(INIT.EQ.0)THEN + NULLIFY(B0F_BT) + INIT=1 + ENDIF + ALLOCATE(ITEM) + ITEM%P2=P2 + ITEM%M12=M12 + ITEM%M22=M22 + FIND=.FALSE. + CALL MP_B0F_SEARCH(ITEM, B0F_BT, FIND) + IF(FIND)THEN + MP_B0F=ITEM%VALUE + DEALLOCATE(ITEM) + RETURN + ELSE + LOGTERMS=MP_LOG_TRAJECTORY(100,P2,M12,M22) + MP_B0F=-LOG(P2/M22)+LOGTERMS + ITEM%VALUE=MP_B0F + RETURN + ENDIF + ELSE + LOGTERMS=MP_LOG_TRAJECTORY(100,P2,M12,M22) + MP_B0F=-LOG(P2/M22)+LOGTERMS + ENDIF + RETURN + END + + COMPLEX*32 FUNCTION MP_SQRT_TRAJECTORY(N_SEG,P2,M12,M22) + IMPLICIT NONE + INTEGER N_SEG + COMPLEX*32 P2,M12,M22 + COMPLEX*32 ZERO,ONE + PARAMETER (ZERO=(0.0E0_16,0.0E0_16),ONE=(1.0E0_16,0.0E0_16)) + COMPLEX*32 GAMMA0,GAMMA1 + REAL*16 M,GA,DGA,GA_START + REAL*16 GAI,INTERSECTION + COMPLEX*32 ARGIM1,ARGI,P2I + COMPLEX*32 GAMMA0I,GAMMA1I + REAL*16 TINY + PARAMETER (TINY=-1.0E-24_16) + INTEGER I + REAL*16 PREFACTOR + IF(ABS(P2*M12*M22).EQ.0.0E0_16)THEN + WRITE(*,*)'ERROR:mp_sqrt_trajectory works when p2*m12*m22' + $ //'/=0' + STOP + ENDIF + M=REAL(P2,KIND=16) + M=SQRT(ABS(M)) + IF(M.EQ.0.0E0_16)THEN + GA=0.0E0_16 + ELSE + GA=-IMAGPART(P2)/M + ENDIF + GAMMA0=ONE+M12/P2-M22/P2 + GAMMA1=M12/P2-CMPLX(0.0E0_16,1.0E0_16)*ABS(TINY)/P2 + IF(ABS(GA).EQ.0.0E0_16)THEN + MP_SQRT_TRAJECTORY=SQRT(GAMMA0**2-4.0E0_16*GAMMA1) + RETURN + ENDIF + GA_START=-ABS(TINY*GA) + DGA=(GA-GA_START)/N_SEG + PREFACTOR=1.0E0_16 + GAI=GA_START + P2I=CMPLX(M**2,-GAI*M) + GAMMA0I=ONE+M12/P2I-M22/P2I + GAMMA1I=M12/P2I-CMPLX(0.0E0_16,1.0E0_16)*ABS(TINY)/P2I + ARGIM1=GAMMA0I**2-4.0E0_16*GAMMA1I + DO I=1,N_SEG + GAI=DGA*I+GA_START + P2I=CMPLX(M**2,-GAI*M) + GAMMA0I=ONE+M12/P2I-M22/P2I + GAMMA1I=M12/P2I-CMPLX(0.0E0_16,1.0E0_16)*ABS(TINY)/P2I + ARGI=GAMMA0I**2-4.0E0_16*GAMMA1I + IF(IMAGPART(ARGI)*IMAGPART(ARGIM1).LT.0.0E0_16)THEN + INTERSECTION=IMAGPART(ARGIM1)*(REAL(ARGI,KIND=16) + $ -REAL(ARGIM1,KIND=16)) + INTERSECTION=INTERSECTION/(IMAGPART(ARGI) + $ -IMAGPART(ARGIM1)) + INTERSECTION=INTERSECTION-REAL(ARGIM1,KIND=16) + IF(INTERSECTION.GT.0.0E0_16)THEN + PREFACTOR=-PREFACTOR + ENDIF + ENDIF + ARGIM1=ARGI + ENDDO + MP_SQRT_TRAJECTORY=SQRT(GAMMA0**2-4.0E0_16*GAMMA1)*PREFACTOR + RETURN + END + + COMPLEX*32 FUNCTION MP_LOG_TRAJECTORY(N_SEG,P2,M12,M22) + IMPLICIT NONE + INTEGER N_SEG + COMPLEX*32 P2,M12,M22 + COMPLEX*32 ZERO,ONE,HALF,TWOPII + PARAMETER (ZERO=(0.0E0_16,0.0E0_16),ONE=(1.0E0_16,0.0E0_16)) + PARAMETER (HALF=(0.5E0_16,0.0E0_16)) + PARAMETER (TWOPII=2.0E0_16 + $ *3.14169258478796109557151794433593750E0_16*(0.0E0_16 + $ ,1.0E0_16)) + COMPLEX*32 GAMMA0,GAMMAP,GAMMAM,SQRTTERM + REAL*16 M,GA,DGA,GA_START + REAL*16 GAI,INTERSECTION + COMPLEX*32 ARGIM1(4),ARGI(4),P2I,SQRTTERMI + COMPLEX*32 GAMMA0I,GAMMAPI,GAMMAMI + REAL*16 TINY + PARAMETER (TINY=-1.0E-14_16) + INTEGER I,J + COMPLEX*32 ADDFACTOR(4) + COMPLEX*32 MP_SQRT_TRAJECTORY + IF(ABS(P2*M12*M22).EQ.0.0E0_16)THEN + WRITE(*,*)'ERROR:mp_log_trajectory works when p2*m12*m22' + $ //'/=0' + STOP + ENDIF + M=REAL(P2,KIND=16) + M=SQRT(ABS(M)) + IF(M.EQ.0.0E0_16)THEN + GA=0.0E0_16 + ELSE + GA=-IMAGPART(P2)/M + ENDIF + SQRTTERM=MP_SQRT_TRAJECTORY(N_SEG,P2,M12,M22) + GAMMA0=ONE+M12/P2-M22/P2 + GAMMAP=HALF*(GAMMA0+SQRTTERM) + GAMMAM=HALF*(GAMMA0-SQRTTERM) + IF(ABS(GA).EQ.0.0E0_16)THEN + MP_LOG_TRAJECTORY=-LOG(GAMMAP-ONE)-LOG(GAMMAM-ONE)+GAMMAP + $ *LOG((GAMMAP-ONE)/GAMMAP)+GAMMAM*LOG((GAMMAM-ONE)/GAMMAM) + RETURN + ENDIF + GA_START=-ABS(TINY*GA) + DGA=(GA-GA_START)/N_SEG + ADDFACTOR(1:4)=ZERO + GAI=GA_START + P2I=CMPLX(M**2,-GAI*M) + SQRTTERMI=MP_SQRT_TRAJECTORY(N_SEG,P2I,M12,M22) + GAMMA0I=ONE+M12/P2I-M22/P2I + GAMMAPI=HALF*(GAMMA0I+SQRTTERMI) + GAMMAMI=HALF*(GAMMA0I-SQRTTERMI) + ARGIM1(1)=GAMMAPI-ONE + ARGIM1(2)=GAMMAMI-ONE + ARGIM1(3)=(GAMMAPI-ONE)/GAMMAPI + ARGIM1(4)=(GAMMAMI-ONE)/GAMMAMI + DO I=1,N_SEG + GAI=DGA*I+GA_START + P2I=CMPLX(M**2,-GAI*M) + SQRTTERMI=MP_SQRT_TRAJECTORY(N_SEG,P2I,M12,M22) + GAMMA0I=ONE+M12/P2I-M22/P2I + GAMMAPI=HALF*(GAMMA0I+SQRTTERMI) + GAMMAMI=HALF*(GAMMA0I-SQRTTERMI) + ARGI(1)=GAMMAPI-ONE + ARGI(2)=GAMMAMI-ONE + ARGI(3)=(GAMMAPI-ONE)/GAMMAPI + ARGI(4)=(GAMMAMI-ONE)/GAMMAMI + DO J=1,4 + IF(IMAGPART(ARGI(J))*IMAGPART(ARGIM1(J)).LT.0.0E0_16)THEN + INTERSECTION=IMAGPART(ARGIM1(J))*(REAL(ARGI(J),KIND=16) + $ -REAL(ARGIM1(J),KIND=16)) + INTERSECTION=INTERSECTION/(IMAGPART(ARGI(J)) + $ -IMAGPART(ARGIM1(J))) + INTERSECTION=INTERSECTION-REAL(ARGIM1(J),KIND=16) + IF(INTERSECTION.GT.0.0E0_16)THEN + IF(IMAGPART(ARGIM1(J)).LT.0.0E0_16)THEN + ADDFACTOR(J)=ADDFACTOR(J)-TWOPII + ELSE + ADDFACTOR(J)=ADDFACTOR(J)+TWOPII + ENDIF + ENDIF + ENDIF + ARGIM1(J)=ARGI(J) + ENDDO + ENDDO + MP_LOG_TRAJECTORY=-(LOG(GAMMAP-ONE)+ADDFACTOR(1)) + $ -(LOG(GAMMAM-ONE)+ADDFACTOR(2)) + MP_LOG_TRAJECTORY=MP_LOG_TRAJECTORY+GAMMAP*(LOG((GAMMAP-ONE) + $ /GAMMAP)+ADDFACTOR(3)) + MP_LOG_TRAJECTORY=MP_LOG_TRAJECTORY+GAMMAM*(LOG((GAMMAM-ONE) + $ /GAMMAM)+ADDFACTOR(4)) + RETURN + END + + COMPLEX*32 FUNCTION MP_ARG(COMNUM) + IMPLICIT NONE + COMPLEX*32 COMNUM + COMPLEX*32 IMM + IMM = (0.0E0_16,1.0E0_16) + IF(COMNUM.EQ.(0.0E0_16,0.0E0_16)) THEN + MP_ARG=(0.0E0_16,0.0E0_16) + ELSE + MP_ARG=LOG(COMNUM/ABS(COMNUM))/IMM + ENDIF + END diff --git a/UNITTEST_proc/Source/MODEL/model_functions.inc b/UNITTEST_proc/Source/MODEL/model_functions.inc new file mode 100644 index 0000000000..226ecdc380 --- /dev/null +++ b/UNITTEST_proc/Source/MODEL/model_functions.inc @@ -0,0 +1,32 @@ +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +c written by the UFO converter +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc + + DOUBLE COMPLEX COND + DOUBLE COMPLEX CONDIF + DOUBLE COMPLEX REGLOG + DOUBLE COMPLEX REGLOGP + DOUBLE COMPLEX REGLOGM + DOUBLE COMPLEX REGSQRT + DOUBLE COMPLEX GRREGLOG + DOUBLE COMPLEX RECMS + DOUBLE COMPLEX ARG + DOUBLE COMPLEX B0F + DOUBLE COMPLEX SQRT_TRAJECTORY + DOUBLE COMPLEX LOG_TRAJECTORY + + + COMPLEX*32 MP_COND + COMPLEX*32 MP_CONDIF + COMPLEX*32 MP_REGLOG + COMPLEX*32 MP_REGLOGP + COMPLEX*32 MP_REGLOGM + COMPLEX*32 MP_REGSQRT + COMPLEX*32 MP_GRREGLOG + COMPLEX*32 MP_RECMS + COMPLEX*32 MP_ARG + COMPLEX*32 MP_B0F + COMPLEX*32 MP_SQRT_TRAJECTORY + COMPLEX*32 MP_LOG_TRAJECTORY + + diff --git a/UNITTEST_proc/Source/MODEL/mp_coupl.inc b/UNITTEST_proc/Source/MODEL/mp_coupl.inc new file mode 100644 index 0000000000..22d5fb5b98 --- /dev/null +++ b/UNITTEST_proc/Source/MODEL/mp_coupl.inc @@ -0,0 +1,44 @@ +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +c written by the UFO converter +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc + + REAL*16 MP__G + COMMON/MP_STRONG/ MP__G + + COMPLEX*32 MP__GAL(2) + COMMON/MP_WEAK/ MP__GAL + + COMPLEX*32 MP__MU_R + COMMON/MP_RSCALE/ MP__MU_R + + + REAL*16 MP__MDL_MB,MP__MDL_MH,MP__MDL_MT,MP__MDL_MTA,MP__MDL_MW + $ ,MP__MDL_MZ + + COMMON/MP_MASSES/ MP__MDL_MB,MP__MDL_MH,MP__MDL_MT,MP__MDL_MTA + $ ,MP__MDL_MW,MP__MDL_MZ + + + REAL*16 MP__MDL_WH,MP__MDL_WT,MP__MDL_WW,MP__MDL_WZ + + COMMON/MP_WIDTHS/ MP__MDL_WH,MP__MDL_WT,MP__MDL_WW,MP__MDL_WZ + + + COMPLEX*32 MP__GC_4,MP__GC_5,MP__GC_6,MP__R2_3GQ,MP__R2_3GG + $ ,MP__R2_GQQ,MP__R2_GGQ,MP__R2_GGB,MP__R2_GGT,MP__R2_GGG_1 + $ ,MP__R2_GGG_2,MP__R2_QQQ,MP__R2_QQT,MP__UV_3GG_1EPS + $ ,MP__UV_3GB_1EPS,MP__UV_GQQG_1EPS,MP__UV_GQQB_1EPS + $ ,MP__UV_TMASS_1EPS,MP__UVWFCT_B_0_1EPS,MP__UVWFCT_G_1_1EPS + $ ,MP__UV_3GB,MP__UV_3GT,MP__UV_GQQB,MP__UV_GQQT,MP__UV_TMASS + $ ,MP__UVWFCT_T_0,MP__UVWFCT_G_1,MP__UVWFCT_G_2 + + COMMON/MP_COUPLINGS/ MP__GC_4,MP__GC_5,MP__GC_6,MP__R2_3GQ + $ ,MP__R2_3GG,MP__R2_GQQ,MP__R2_GGQ,MP__R2_GGB,MP__R2_GGT + $ ,MP__R2_GGG_1,MP__R2_GGG_2,MP__R2_QQQ,MP__R2_QQT + $ ,MP__UV_3GG_1EPS,MP__UV_3GB_1EPS,MP__UV_GQQG_1EPS + $ ,MP__UV_GQQB_1EPS,MP__UV_TMASS_1EPS,MP__UVWFCT_B_0_1EPS + $ ,MP__UVWFCT_G_1_1EPS,MP__UV_3GB,MP__UV_3GT,MP__UV_GQQB + $ ,MP__UV_GQQT,MP__UV_TMASS,MP__UVWFCT_T_0,MP__UVWFCT_G_1 + $ ,MP__UVWFCT_G_2 + + diff --git a/UNITTEST_proc/Source/MODEL/mp_coupl_same_name.inc b/UNITTEST_proc/Source/MODEL/mp_coupl_same_name.inc new file mode 100644 index 0000000000..6046aa3364 --- /dev/null +++ b/UNITTEST_proc/Source/MODEL/mp_coupl_same_name.inc @@ -0,0 +1,37 @@ +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +c written by the UFO converter +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc + + REAL*16 G + COMMON/MP_STRONG/ G + + COMPLEX*32 GAL(2) + COMMON/MP_WEAK/ GAL + + COMPLEX*32 MU_R + COMMON/MP_RSCALE/ MU_R + + + REAL*16 MDL_MB,MDL_MH,MDL_MT,MDL_MTA,MDL_MW,MDL_MZ + + COMMON/MP_MASSES/ MDL_MB,MDL_MH,MDL_MT,MDL_MTA,MDL_MW,MDL_MZ + + + REAL*16 MDL_WH,MDL_WT,MDL_WW,MDL_WZ + + COMMON/MP_WIDTHS/ MDL_WH,MDL_WT,MDL_WW,MDL_WZ + + + COMPLEX*32 GC_4,GC_5,GC_6,R2_3GQ,R2_3GG,R2_GQQ,R2_GGQ,R2_GGB + $ ,R2_GGT,R2_GGG_1,R2_GGG_2,R2_QQQ,R2_QQT,UV_3GG_1EPS,UV_3GB_1EPS + $ ,UV_GQQG_1EPS,UV_GQQB_1EPS,UV_TMASS_1EPS,UVWFCT_B_0_1EPS + $ ,UVWFCT_G_1_1EPS,UV_3GB,UV_3GT,UV_GQQB,UV_GQQT,UV_TMASS + $ ,UVWFCT_T_0,UVWFCT_G_1,UVWFCT_G_2 + + COMMON/MP_COUPLINGS/ GC_4,GC_5,GC_6,R2_3GQ,R2_3GG,R2_GQQ,R2_GGQ + $ ,R2_GGB,R2_GGT,R2_GGG_1,R2_GGG_2,R2_QQQ,R2_QQT,UV_3GG_1EPS + $ ,UV_3GB_1EPS,UV_GQQG_1EPS,UV_GQQB_1EPS,UV_TMASS_1EPS + $ ,UVWFCT_B_0_1EPS,UVWFCT_G_1_1EPS,UV_3GB,UV_3GT,UV_GQQB,UV_GQQT + $ ,UV_TMASS,UVWFCT_T_0,UVWFCT_G_1,UVWFCT_G_2 + + diff --git a/UNITTEST_proc/Source/MODEL/mp_couplings1.f b/UNITTEST_proc/Source/MODEL/mp_couplings1.f new file mode 100644 index 0000000000..204304467d --- /dev/null +++ b/UNITTEST_proc/Source/MODEL/mp_couplings1.f @@ -0,0 +1,16 @@ +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +c written by the UFO converter +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc + + SUBROUTINE MP_COUP1( ) + USE MODEL_OBJECT + IMPLICIT NONE + + INCLUDE 'model_functions.inc' + REAL*16 MP__PI, MP__ZERO + PARAMETER (MP__PI=3.1415926535897932384626433832795E0_16) + PARAMETER (MP__ZERO=0E0_16) + INCLUDE 'mp_input.inc' + INCLUDE 'mp_coupl.inc' + + END diff --git a/UNITTEST_proc/Source/MODEL/mp_couplings2.f b/UNITTEST_proc/Source/MODEL/mp_couplings2.f new file mode 100644 index 0000000000..b69c61d50d --- /dev/null +++ b/UNITTEST_proc/Source/MODEL/mp_couplings2.f @@ -0,0 +1,16 @@ +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +c written by the UFO converter +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc + + SUBROUTINE MP_COUP2( ) + USE MODEL_OBJECT + IMPLICIT NONE + + INCLUDE 'model_functions.inc' + REAL*16 MP__PI, MP__ZERO + PARAMETER (MP__PI=3.1415926535897932384626433832795E0_16) + PARAMETER (MP__ZERO=0E0_16) + INCLUDE 'mp_input.inc' + INCLUDE 'mp_coupl.inc' + + END diff --git a/UNITTEST_proc/Source/MODEL/mp_couplings3.f b/UNITTEST_proc/Source/MODEL/mp_couplings3.f new file mode 100644 index 0000000000..1b1a1d5cca --- /dev/null +++ b/UNITTEST_proc/Source/MODEL/mp_couplings3.f @@ -0,0 +1,80 @@ +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +c written by the UFO converter +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc + + SUBROUTINE MP_COUP3( ) + USE MODEL_OBJECT + IMPLICIT NONE + + INCLUDE 'model_functions.inc' + REAL*16 MP__PI, MP__ZERO + PARAMETER (MP__PI=3.1415926535897932384626433832795E0_16) + PARAMETER (MP__ZERO=0E0_16) + INCLUDE 'mp_input.inc' + INCLUDE 'mp_coupl.inc' + + MP__GC_4 = -MP__G + MP__GC_5 = MP__MDL_COMPLEXI*MP__G + MP__GC_6 = MP__MDL_COMPLEXI*MP__MDL_G__EXP__2 + MP__R2_3GQ = 2.000000E+00_16*MP__MDL_G__EXP__3/(4.800000E+01_16 + $ *MP__PI**2) + MP__R2_3GG = MP__MDL_NCOL*MP__MDL_G__EXP__3/(4.800000E+01_16 + $ *MP__PI**2)*(7.000000E+00_16/4.000000E+00_16+MP__MDL_LHV) + MP__R2_GQQ = -MP__MDL_COMPLEXI*MP__MDL_G__EXP__3/(1.600000E + $ +01_16*MP__PI**2)*((MP__MDL_NCOL__EXP__2-1.000000E+00_16) + $ /(2.000000E+00_16*MP__MDL_NCOL))*(1.000000E+00_16+MP__MDL_LHV) + MP__R2_GGQ = (2.000000E+00_16)*MP__MDL_COMPLEXI + $ *MP__MDL_G__EXP__2/(4.800000E+01_16*MP__PI**2) + MP__R2_GGB = (2.000000E+00_16)*MP__MDL_COMPLEXI + $ *MP__MDL_G__EXP__2*(-6.000000E+00_16*MP__MDL_MB__EXP__2) + $ /(4.800000E+01_16*MP__PI**2) + MP__R2_GGT = (2.000000E+00_16)*MP__MDL_COMPLEXI + $ *MP__MDL_G__EXP__2*(-6.000000E+00_16*MP__MDL_MT__EXP__2) + $ /(4.800000E+01_16*MP__PI**2) + MP__R2_GGG_1 = (2.000000E+00_16)*MP__MDL_COMPLEXI + $ *MP__MDL_G__EXP__2*MP__MDL_NCOL/(4.800000E+01_16*MP__PI**2) + $ *(1.000000E+00_16/2.000000E+00_16+MP__MDL_LHV) + MP__R2_GGG_2 = -(2.000000E+00_16)*MP__MDL_COMPLEXI + $ *MP__MDL_G__EXP__2*MP__MDL_NCOL/(4.800000E+01_16*MP__PI**2) + $ *MP__MDL_LHV + MP__R2_QQQ = MP__MDL_LHV*MP__MDL_COMPLEXI*MP__MDL_G__EXP__2 + $ *(MP__MDL_NCOL__EXP__2-1.000000E+00_16)/(3.200000E+01_16*MP__PI + $ **2*MP__MDL_NCOL) + MP__R2_QQT = MP__MDL_LHV*MP__MDL_COMPLEXI*MP__MDL_G__EXP__2 + $ *(MP__MDL_NCOL__EXP__2-1.000000E+00_16)*(2.000000E+00_16 + $ *MP__MDL_MT)/(3.200000E+01_16*MP__PI**2*MP__MDL_NCOL) + MP__UV_3GG_1EPS = -MP__MDL_G_UVG_1EPS_*MP__G + MP__UV_3GB_1EPS = -MP__MDL_G_UVB_1EPS_*MP__G + MP__UV_GQQG_1EPS = MP__MDL_COMPLEXI*MP__MDL_G_UVG_1EPS_*MP__G + MP__UV_GQQB_1EPS = MP__MDL_COMPLEXI*MP__MDL_G_UVB_1EPS_*MP__G + MP__UV_TMASS_1EPS = MP__MDL_TMASS_UV_1EPS_ + MP__UVWFCT_B_0_1EPS = MP_COND(CMPLX(MP__MDL_MB,KIND=16) + $ ,CMPLX(0.000000E+00_16,KIND=16),CMPLX(-((MP__MDL_G__EXP__2) + $ /(2.000000E+00_16*1.600000E+01_16*MP__PI**2))*3.000000E+00_16 + $ *MP__MDL_CF,KIND=16)) + MP__UVWFCT_G_1_1EPS = MP_COND(CMPLX(MP__MDL_MB,KIND=16) + $ ,CMPLX(0.000000E+00_16,KIND=16),CMPLX(-((MP__MDL_G__EXP__2) + $ /(2.000000E+00_16*4.800000E+01_16*MP__PI**2))*4.000000E+00_16 + $ *MP__MDL_TF,KIND=16)) + MP__UV_3GB = -MP__MDL_G_UVB_FIN_*MP__G + MP__UV_3GT = -MP__MDL_G_UVT_FIN_*MP__G + MP__UV_GQQB = MP__MDL_COMPLEXI*MP__MDL_G_UVB_FIN_*MP__G + MP__UV_GQQT = MP__MDL_COMPLEXI*MP__MDL_G_UVT_FIN_*MP__G + MP__UV_TMASS = MP__MDL_TMASS_UV_FIN_ + MP__UVWFCT_T_0 = MP_COND(CMPLX(MP__MDL_MT,KIND=16) + $ ,CMPLX(0.000000E+00_16,KIND=16),CMPLX(-((MP__MDL_G__EXP__2) + $ /(2.000000E+00_16*1.600000E+01_16*MP__PI**2))*MP__MDL_CF + $ *(4.000000E+00_16-3.000000E+00_16 + $ *MP_REGLOG(CMPLX((MP__MDL_MT__EXP__2/MP__MDL_MU_R__EXP__2) + $ ,KIND=16))),KIND=16)) + MP__UVWFCT_G_1 = MP_COND(CMPLX(MP__MDL_MB,KIND=16) + $ ,CMPLX(0.000000E+00_16,KIND=16),CMPLX(((MP__MDL_G__EXP__2) + $ /(2.000000E+00_16*4.800000E+01_16*MP__PI**2))*4.000000E+00_16 + $ *MP__MDL_TF*MP_REGLOG(CMPLX((MP__MDL_MB__EXP__2 + $ /MP__MDL_MU_R__EXP__2),KIND=16)),KIND=16)) + MP__UVWFCT_G_2 = MP_COND(CMPLX(MP__MDL_MT,KIND=16) + $ ,CMPLX(0.000000E+00_16,KIND=16),CMPLX(((MP__MDL_G__EXP__2) + $ /(2.000000E+00_16*4.800000E+01_16*MP__PI**2))*4.000000E+00_16 + $ *MP__MDL_TF*MP_REGLOG(CMPLX((MP__MDL_MT__EXP__2 + $ /MP__MDL_MU_R__EXP__2),KIND=16)),KIND=16)) + END diff --git a/UNITTEST_proc/Source/MODEL/mp_input.inc b/UNITTEST_proc/Source/MODEL/mp_input.inc new file mode 100644 index 0000000000..bbdb87fb29 --- /dev/null +++ b/UNITTEST_proc/Source/MODEL/mp_input.inc @@ -0,0 +1,56 @@ +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +c written by the UFO converter +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc + + REAL*16 MP__MDL_SQRT__AS,MP__MDL_G__EXP__4,MP__MDL_G__EXP__2 + $ ,MP__MDL_G_UVG_1EPS_,MP__MDL_G_UVB_1EPS_,MP__MDL_G__EXP__3 + $ ,MP__MDL_MU_R__EXP__2,MP__MDL_G_UVB_FIN_,MP__MDL_G_UVT_FIN_ + $ ,MP__MDL_LHV,MP__MDL_CONJG__CKM3X3,MP__MDL_CONJG__CKM22 + $ ,MP__MDL_CKM3X3,MP__MDL_CKM33,MP__MDL_CKM22,MP__MDL_NCOL + $ ,MP__MDL_CA,MP__MDL_TF,MP__MDL_CF,MP__MDL_MZ__EXP__2 + $ ,MP__MDL_MZ__EXP__4,MP__MDL_SQRT__2,MP__MDL_MH__EXP__2 + $ ,MP__MDL_NCOL__EXP__2,MP__MDL_MB__EXP__2,MP__MDL_MT__EXP__2 + $ ,MP__MDL_AEW,MP__MDL_SQRT__AEW,MP__MDL_EE,MP__MDL_VECTORAUP + $ ,MP__MDL_VECTORADOWN,MP__MDL_EE__EXP__2,MP__MDL_MW__EXP__2 + $ ,MP__MDL_SW2,MP__MDL_CW,MP__MDL_SQRT__SW2,MP__MDL_SW,MP__MDL_G1 + $ ,MP__MDL_GW,MP__MDL_V,MP__MDL_V__EXP__2,MP__MDL_LAM,MP__MDL_YB + $ ,MP__MDL_YT,MP__MDL_YTAU,MP__MDL_MUH,MP__MDL_AXIALZUP + $ ,MP__MDL_AXIALZDOWN,MP__MDL_VECTORZUP,MP__MDL_VECTORZDOWN + $ ,MP__MDL_VECTORWMDXU,MP__MDL_AXIALWMDXU,MP__MDL_VECTORWPUXD + $ ,MP__MDL_AXIALWPUXD,MP__MDL_GW__EXP__2,MP__MDL_CW__EXP__2 + $ ,MP__MDL_SW__EXP__2,MP__MDL_YB__EXP__2,MP__MDL_YT__EXP__2 + $ ,MP__AEWM1,MP__MDL_GF,MP__AS,MP__MDL_YMB,MP__MDL_YMT + $ ,MP__MDL_YMTAU + + COMMON/MP_T_PARAMS_R/ MP__MDL_SQRT__AS,MP__MDL_G__EXP__4 + $ ,MP__MDL_G__EXP__2,MP__MDL_G_UVG_1EPS_,MP__MDL_G_UVB_1EPS_ + $ ,MP__MDL_G__EXP__3,MP__MDL_MU_R__EXP__2,MP__MDL_G_UVB_FIN_ + $ ,MP__MDL_G_UVT_FIN_,MP__MDL_LHV,MP__MDL_CONJG__CKM3X3 + $ ,MP__MDL_CONJG__CKM22,MP__MDL_CKM3X3,MP__MDL_CKM33 + $ ,MP__MDL_CKM22,MP__MDL_NCOL,MP__MDL_CA,MP__MDL_TF,MP__MDL_CF + $ ,MP__MDL_MZ__EXP__2,MP__MDL_MZ__EXP__4,MP__MDL_SQRT__2 + $ ,MP__MDL_MH__EXP__2,MP__MDL_NCOL__EXP__2,MP__MDL_MB__EXP__2 + $ ,MP__MDL_MT__EXP__2,MP__MDL_AEW,MP__MDL_SQRT__AEW,MP__MDL_EE + $ ,MP__MDL_VECTORAUP,MP__MDL_VECTORADOWN,MP__MDL_EE__EXP__2 + $ ,MP__MDL_MW__EXP__2,MP__MDL_SW2,MP__MDL_CW,MP__MDL_SQRT__SW2 + $ ,MP__MDL_SW,MP__MDL_G1,MP__MDL_GW,MP__MDL_V,MP__MDL_V__EXP__2 + $ ,MP__MDL_LAM,MP__MDL_YB,MP__MDL_YT,MP__MDL_YTAU,MP__MDL_MUH + $ ,MP__MDL_AXIALZUP,MP__MDL_AXIALZDOWN,MP__MDL_VECTORZUP + $ ,MP__MDL_VECTORZDOWN,MP__MDL_VECTORWMDXU,MP__MDL_AXIALWMDXU + $ ,MP__MDL_VECTORWPUXD,MP__MDL_AXIALWPUXD,MP__MDL_GW__EXP__2 + $ ,MP__MDL_CW__EXP__2,MP__MDL_SW__EXP__2,MP__MDL_YB__EXP__2 + $ ,MP__MDL_YT__EXP__2,MP__AEWM1,MP__MDL_GF,MP__AS,MP__MDL_YMB + $ ,MP__MDL_YMT,MP__MDL_YMTAU + + + COMPLEX*32 MP__MDL_TMASS_UV_1EPS_,MP__MDL_TMASS_UV_FIN_ + $ ,MP__MDL_COMPLEXI,MP__MDL_I1X33,MP__MDL_I2X33,MP__MDL_I3X33 + $ ,MP__MDL_I4X33,MP__MDL_VECTOR_TBGP,MP__MDL_AXIAL_TBGP + $ ,MP__MDL_VECTOR_TBGM,MP__MDL_AXIAL_TBGM + + COMMON/MP_PARAMS_C/ MP__MDL_TMASS_UV_1EPS_,MP__MDL_TMASS_UV_FIN_ + $ ,MP__MDL_COMPLEXI,MP__MDL_I1X33,MP__MDL_I2X33,MP__MDL_I3X33 + $ ,MP__MDL_I4X33,MP__MDL_VECTOR_TBGP,MP__MDL_AXIAL_TBGP + $ ,MP__MDL_VECTOR_TBGM,MP__MDL_AXIAL_TBGM + + diff --git a/UNITTEST_proc/Source/MODEL/mp_intparam_definition.inc b/UNITTEST_proc/Source/MODEL/mp_intparam_definition.inc new file mode 100644 index 0000000000..e52d2947f0 --- /dev/null +++ b/UNITTEST_proc/Source/MODEL/mp_intparam_definition.inc @@ -0,0 +1,210 @@ +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +c written by the UFO converter +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc + +C Parameters that should not be recomputed event by event. +C + IF(READLHA) THEN + + MP__G = 2 * SQRT(MP__AS*MP__PI) ! for the first init + + MP__MDL_LHV = 1.000000E+00_16 + + MP__MDL_CONJG__CKM3X3 = 1.000000E+00_16 + + MP__MDL_CONJG__CKM22 = 1.000000E+00_16 + + MP__MDL_CKM3X3 = 1.000000E+00_16 + + MP__MDL_CKM33 = 1.000000E+00_16 + + MP__MDL_CKM22 = 1.000000E+00_16 + + MP__MDL_NCOL = 3.000000E+00_16 + + MP__MDL_CA = 3.000000E+00_16 + + MP__MDL_TF = 5.000000E-01_16 + + MP__MDL_CF = (4.000000E+00_16/3.000000E+00_16) + + MP__MDL_COMPLEXI = CMPLX(0.000000E+00_16,1.000000E+00_16 + $ ,KIND=16) + + MP__MDL_MZ__EXP__2 = MP__MDL_MZ**2 + + MP__MDL_MZ__EXP__4 = MP__MDL_MZ**4 + + MP__MDL_SQRT__2 = SQRT(CMPLX((2.000000E+00_16),KIND=16)) + + MP__MDL_MH__EXP__2 = MP__MDL_MH**2 + + MP__MDL_NCOL__EXP__2 = MP__MDL_NCOL**2 + + MP__MDL_MB__EXP__2 = MP__MDL_MB**2 + + MP__MDL_MT__EXP__2 = MP__MDL_MT**2 + + MP__MDL_AEW = 1.000000E+00_16/MP__AEWM1 + + MP__MDL_SQRT__AEW = SQRT(CMPLX((MP__MDL_AEW),KIND=16)) + + MP__MDL_EE = 2.000000E+00_16*MP__MDL_SQRT__AEW + $ *SQRT(CMPLX((MP__PI),KIND=16)) + + MP__MDL_VECTORAUP = (2.000000E+00_16*MP__MDL_EE)/3.000000E + $ +00_16 + + MP__MDL_VECTORADOWN = -(MP__MDL_EE)/3.000000E+00_16 + + MP__MDL_EE__EXP__2 = MP__MDL_EE**2 + + MP__MDL_MW = SQRT(CMPLX((MP__MDL_MZ__EXP__2/2.000000E+00_16 + $ +SQRT(CMPLX((MP__MDL_MZ__EXP__4/4.000000E+00_16-(MP__MDL_AEW + $ *MP__PI*MP__MDL_MZ__EXP__2)/(MP__MDL_GF*MP__MDL_SQRT__2)) + $ ,KIND=16))),KIND=16)) + + MP__MDL_MW__EXP__2 = MP__MDL_MW**2 + + MP__MDL_SW2 = 1.000000E+00_16-MP__MDL_MW__EXP__2 + $ /MP__MDL_MZ__EXP__2 + + MP__MDL_CW = SQRT(CMPLX((1.000000E+00_16-MP__MDL_SW2),KIND=16)) + + MP__MDL_SQRT__SW2 = SQRT(CMPLX((MP__MDL_SW2),KIND=16)) + + MP__MDL_SW = MP__MDL_SQRT__SW2 + + MP__MDL_G1 = MP__MDL_EE/MP__MDL_CW + + MP__MDL_GW = MP__MDL_EE/MP__MDL_SW + + MP__MDL_V = (2.000000E+00_16*MP__MDL_MW*MP__MDL_SW)/MP__MDL_EE + + MP__MDL_V__EXP__2 = MP__MDL_V**2 + + MP__MDL_LAM = MP__MDL_MH__EXP__2/(2.000000E+00_16 + $ *MP__MDL_V__EXP__2) + + MP__MDL_YB = (MP__MDL_YMB*MP__MDL_SQRT__2)/MP__MDL_V + + MP__MDL_YT = (MP__MDL_YMT*MP__MDL_SQRT__2)/MP__MDL_V + + MP__MDL_YTAU = (MP__MDL_YMTAU*MP__MDL_SQRT__2)/MP__MDL_V + + MP__MDL_MUH = SQRT(CMPLX((MP__MDL_LAM*MP__MDL_V__EXP__2) + $ ,KIND=16)) + + MP__MDL_AXIALZUP = (3.000000E+00_16/2.000000E+00_16)*( + $ -(MP__MDL_EE*MP__MDL_SW)/(6.000000E+00_16*MP__MDL_CW)) + $ -(1.000000E+00_16/2.000000E+00_16)*((MP__MDL_CW*MP__MDL_EE) + $ /(2.000000E+00_16*MP__MDL_SW)) + + MP__MDL_AXIALZDOWN = (-1.000000E+00_16/2.000000E+00_16)*( + $ -(MP__MDL_CW*MP__MDL_EE)/(2.000000E+00_16*MP__MDL_SW))+( + $ -3.000000E+00_16/2.000000E+00_16)*(-(MP__MDL_EE*MP__MDL_SW) + $ /(6.000000E+00_16*MP__MDL_CW)) + + MP__MDL_VECTORZUP = (1.000000E+00_16/2.000000E+00_16) + $ *((MP__MDL_CW*MP__MDL_EE)/(2.000000E+00_16*MP__MDL_SW)) + $ +(5.000000E+00_16/2.000000E+00_16)*(-(MP__MDL_EE*MP__MDL_SW) + $ /(6.000000E+00_16*MP__MDL_CW)) + + MP__MDL_VECTORZDOWN = (1.000000E+00_16/2.000000E+00_16)*( + $ -(MP__MDL_CW*MP__MDL_EE)/(2.000000E+00_16*MP__MDL_SW))+( + $ -1.000000E+00_16/2.000000E+00_16)*(-(MP__MDL_EE*MP__MDL_SW) + $ /(6.000000E+00_16*MP__MDL_CW)) + + MP__MDL_VECTORWMDXU = (1.000000E+00_16/2.000000E+00_16) + $ *((MP__MDL_EE)/(MP__MDL_SW*MP__MDL_SQRT__2)) + + MP__MDL_AXIALWMDXU = (-1.000000E+00_16/2.000000E+00_16) + $ *((MP__MDL_EE)/(MP__MDL_SW*MP__MDL_SQRT__2)) + + MP__MDL_VECTORWPUXD = (1.000000E+00_16/2.000000E+00_16) + $ *((MP__MDL_EE)/(MP__MDL_SW*MP__MDL_SQRT__2)) + + MP__MDL_AXIALWPUXD = -(1.000000E+00_16/2.000000E+00_16) + $ *((MP__MDL_EE)/(MP__MDL_SW*MP__MDL_SQRT__2)) + + MP__MDL_I1X33 = MP__MDL_YB*MP__MDL_CONJG__CKM3X3 + + MP__MDL_I2X33 = MP__MDL_YT*MP__MDL_CONJG__CKM3X3 + + MP__MDL_I3X33 = MP__MDL_CKM3X3*MP__MDL_YT + + MP__MDL_I4X33 = MP__MDL_CKM3X3*MP__MDL_YB + + MP__MDL_VECTOR_TBGP = MP__MDL_I1X33-MP__MDL_I2X33 + + MP__MDL_AXIAL_TBGP = -MP__MDL_I2X33-MP__MDL_I1X33 + + MP__MDL_VECTOR_TBGM = MP__MDL_I3X33-MP__MDL_I4X33 + + MP__MDL_AXIAL_TBGM = -MP__MDL_I4X33-MP__MDL_I3X33 + + MP__MDL_GW__EXP__2 = MP__MDL_GW**2 + + MP__MDL_CW__EXP__2 = MP__MDL_CW**2 + + MP__MDL_SW__EXP__2 = MP__MDL_SW**2 + + MP__MDL_YB__EXP__2 = MP__MDL_YB**2 + + MP__MDL_YT__EXP__2 = MP__MDL_YT**2 + + ENDIF +C +C Parameters that should be recomputed at an event by even basis. +C + MP__AS = MP__G**2/4/MP__PI + + MP__MDL_SQRT__AS = SQRT(CMPLX((MP__AS),KIND=16)) + + MP__MDL_G__EXP__4 = MP__G**4 + + MP__MDL_G__EXP__2 = MP__G**2 + + MP__MDL_G__EXP__3 = MP__G**3 + + MP__MDL_MU_R__EXP__2 = MP__MU_R**2 + +C +C Parameters that should be updated for the loops. +C + MP__MDL_G_UVG_1EPS_ = -((MP__MDL_G__EXP__2)/(2.000000E+00_16 + $ *4.800000E+01_16*MP__PI**2))*1.100000E+01_16*MP__MDL_CA + + MP__MDL_G_UVB_1EPS_ = ((MP__MDL_G__EXP__2)/(2.000000E+00_16 + $ *4.800000E+01_16*MP__PI**2))*4.000000E+00_16*MP__MDL_TF + + MP__MDL_TMASS_UV_1EPS_ = MP_COND(CMPLX(MP__MDL_MT,KIND=16) + $ ,CMPLX(0.000000E+00_16,KIND=16),CMPLX(MP__MDL_COMPLEXI + $ *((MP__MDL_G__EXP__2)/(1.600000E+01_16*MP__PI**2))*3.000000E + $ +00_16*MP__MDL_CF*MP__MDL_MT,KIND=16)) + + MP__MDL_G_UVB_FIN_ = MP_COND(CMPLX(MP__MDL_MB,KIND=16) + $ ,CMPLX(0.000000E+00_16,KIND=16),CMPLX(-((MP__MDL_G__EXP__2) + $ /(2.000000E+00_16*4.800000E+01_16*MP__PI**2))*4.000000E+00_16 + $ *MP__MDL_TF*MP_REGLOG(CMPLX((MP__MDL_MB__EXP__2 + $ /MP__MDL_MU_R__EXP__2),KIND=16)),KIND=16)) + + MP__MDL_G_UVT_FIN_ = MP_COND(CMPLX(MP__MDL_MT,KIND=16) + $ ,CMPLX(0.000000E+00_16,KIND=16),CMPLX(-((MP__MDL_G__EXP__2) + $ /(2.000000E+00_16*4.800000E+01_16*MP__PI**2))*4.000000E+00_16 + $ *MP__MDL_TF*MP_REGLOG(CMPLX((MP__MDL_MT__EXP__2 + $ /MP__MDL_MU_R__EXP__2),KIND=16)),KIND=16)) + + MP__MDL_TMASS_UV_FIN_ = MP_COND(CMPLX(MP__MDL_MT,KIND=16) + $ ,CMPLX(0.000000E+00_16,KIND=16),CMPLX(MP__MDL_COMPLEXI + $ *((MP__MDL_G__EXP__2)/(1.600000E+01_16*MP__PI**2))*MP__MDL_CF + $ *(4.000000E+00_16-3.000000E+00_16 + $ *MP_REGLOG(CMPLX((MP__MDL_MT__EXP__2/MP__MDL_MU_R__EXP__2) + $ ,KIND=16)))*MP__MDL_MT,KIND=16)) + +C +C Definition of the EW coupling used in the write out of aqed +C + MP__GAL(1) = 2 * SQRT(MP__PI/ABS(MP__AEWM1)) + MP__GAL(2) = 1D0 + diff --git a/UNITTEST_proc/Source/MODEL/param_card_rule.dat b/UNITTEST_proc/Source/MODEL/param_card_rule.dat new file mode 100644 index 0000000000..4c8b5702fc --- /dev/null +++ b/UNITTEST_proc/Source/MODEL/param_card_rule.dat @@ -0,0 +1,25 @@ +###################################################################### +## VALIDITY RULE FOR THE PARAM_CARD #### +###################################################################### + + wolfenstein 1 # + wolfenstein 2 # + wolfenstein 3 # + wolfenstein 4 # + yukawa 4 # + yukawa 11 # + yukawa 13 # + mass 4 # + mass 11 # + mass 13 # + decay 15 # + + + + + + + + + + \ No newline at end of file diff --git a/UNITTEST_proc/Source/MODEL/param_read.inc b/UNITTEST_proc/Source/MODEL/param_read.inc new file mode 100644 index 0000000000..896f6b6780 --- /dev/null +++ b/UNITTEST_proc/Source/MODEL/param_read.inc @@ -0,0 +1,57 @@ +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +c written by the UFO converter +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc + + CALL LHA_GET_REAL_SILENT(NPARA,PARAM,VALUE,'MU_R',MU_R,9.118800D + $ +01) + CALL MP_LHA_GET_REAL_SILENT(NPARA,PARAM,VALUE,'MU_R',MP__MU_R + $ ,9.118800E+01_16) + CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'aEWM1',AEWM1,1.325070D+02) + CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'aEWM1',MP__AEWM1 + $ ,1.325070E+02_16) + CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_Gf',MDL_GF,1.166390D-05) + CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_Gf',MP__MDL_GF + $ ,1.166390E-05_16) + CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'aS',AS,1.180000D-01) + CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'aS',MP__AS,1.180000E + $ -01_16) + CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_ymb',MDL_YMB,4.700000D + $ +00) + CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_ymb',MP__MDL_YMB + $ ,4.700000E+00_16) + CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_ymt',MDL_YMT,1.730000D + $ +02) + CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_ymt',MP__MDL_YMT + $ ,1.730000E+02_16) + CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_ymtau',MDL_YMTAU + $ ,1.777000D+00) + CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_ymtau',MP__MDL_YMTAU + $ ,1.777000E+00_16) + CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_MT',MDL_MT,1.730000D+02) + CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_MT',MP__MDL_MT + $ ,1.730000E+02_16) + CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_MB',MDL_MB,4.700000D+00) + CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_MB',MP__MDL_MB + $ ,4.700000E+00_16) + CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_MZ',MDL_MZ,9.118800D+01) + CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_MZ',MP__MDL_MZ + $ ,9.118800E+01_16) + CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_MH',MDL_MH,1.250000D+02) + CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_MH',MP__MDL_MH + $ ,1.250000E+02_16) + CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_MTA',MDL_MTA,1.777000D + $ +00) + CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_MTA',MP__MDL_MTA + $ ,1.777000E+00_16) + CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_WT',MDL_WT,1.491500D+00) + CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_WT',MP__MDL_WT + $ ,1.491500E+00_16) + CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_WZ',MDL_WZ,2.441404D+00) + CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_WZ',MP__MDL_WZ + $ ,2.441404E+00_16) + CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_WW',MDL_WW,2.047600D+00) + CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_WW',MP__MDL_WW + $ ,2.047600E+00_16) + CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_WH',MDL_WH,6.382339D-03) + CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_WH',MP__MDL_WH + $ ,6.382339E-03_16) diff --git a/UNITTEST_proc/Source/MODEL/param_write.inc b/UNITTEST_proc/Source/MODEL/param_write.inc new file mode 100644 index 0000000000..af52890124 --- /dev/null +++ b/UNITTEST_proc/Source/MODEL/param_write.inc @@ -0,0 +1,100 @@ +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +c written by the UFO converter +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc + + WRITE(*,*) ' External Params' + WRITE(*,*) ' ---------------------------------' + WRITE(*,*) ' ' + WRITE(*,*) 'MU_R = ', MU_R + WRITE(*,*) 'mdl_MB = ', MDL_MB + WRITE(*,*) 'mdl_MT = ', MDL_MT + WRITE(*,*) 'mdl_MTA = ', MDL_MTA + WRITE(*,*) 'mdl_MZ = ', MDL_MZ + WRITE(*,*) 'mdl_MH = ', MDL_MH + WRITE(*,*) 'aEWM1 = ', AEWM1 + WRITE(*,*) 'mdl_Gf = ', MDL_GF + WRITE(*,*) 'aS = ', AS + WRITE(*,*) 'mdl_ymb = ', MDL_YMB + WRITE(*,*) 'mdl_ymt = ', MDL_YMT + WRITE(*,*) 'mdl_ymtau = ', MDL_YMTAU + WRITE(*,*) 'mdl_WT = ', MDL_WT + WRITE(*,*) 'mdl_WZ = ', MDL_WZ + WRITE(*,*) 'mdl_WW = ', MDL_WW + WRITE(*,*) 'mdl_WH = ', MDL_WH + WRITE(*,*) ' Internal Params' + WRITE(*,*) ' ---------------------------------' + WRITE(*,*) ' ' + WRITE(*,*) 'mdl_lhv = ', MDL_LHV + WRITE(*,*) 'mdl_conjg__CKM3x3 = ', MDL_CONJG__CKM3X3 + WRITE(*,*) 'mdl_conjg__CKM22 = ', MDL_CONJG__CKM22 + WRITE(*,*) 'mdl_CKM3x3 = ', MDL_CKM3X3 + WRITE(*,*) 'mdl_CKM33 = ', MDL_CKM33 + WRITE(*,*) 'mdl_CKM22 = ', MDL_CKM22 + WRITE(*,*) 'mdl_Ncol = ', MDL_NCOL + WRITE(*,*) 'mdl_CA = ', MDL_CA + WRITE(*,*) 'mdl_TF = ', MDL_TF + WRITE(*,*) 'mdl_CF = ', MDL_CF + WRITE(*,*) 'mdl_complexi = ', MDL_COMPLEXI + WRITE(*,*) 'mdl_MZ__exp__2 = ', MDL_MZ__EXP__2 + WRITE(*,*) 'mdl_MZ__exp__4 = ', MDL_MZ__EXP__4 + WRITE(*,*) 'mdl_sqrt__2 = ', MDL_SQRT__2 + WRITE(*,*) 'mdl_MH__exp__2 = ', MDL_MH__EXP__2 + WRITE(*,*) 'mdl_Ncol__exp__2 = ', MDL_NCOL__EXP__2 + WRITE(*,*) 'mdl_MB__exp__2 = ', MDL_MB__EXP__2 + WRITE(*,*) 'mdl_MT__exp__2 = ', MDL_MT__EXP__2 + WRITE(*,*) 'mdl_aEW = ', MDL_AEW + WRITE(*,*) 'mdl_sqrt__aEW = ', MDL_SQRT__AEW + WRITE(*,*) 'mdl_ee = ', MDL_EE + WRITE(*,*) 'mdl_VectorAUp = ', MDL_VECTORAUP + WRITE(*,*) 'mdl_VectorADown = ', MDL_VECTORADOWN + WRITE(*,*) 'mdl_ee__exp__2 = ', MDL_EE__EXP__2 + WRITE(*,*) 'mdl_MW = ', MDL_MW + WRITE(*,*) 'mdl_MW__exp__2 = ', MDL_MW__EXP__2 + WRITE(*,*) 'mdl_sw2 = ', MDL_SW2 + WRITE(*,*) 'mdl_cw = ', MDL_CW + WRITE(*,*) 'mdl_sqrt__sw2 = ', MDL_SQRT__SW2 + WRITE(*,*) 'mdl_sw = ', MDL_SW + WRITE(*,*) 'mdl_g1 = ', MDL_G1 + WRITE(*,*) 'mdl_gw = ', MDL_GW + WRITE(*,*) 'mdl_v = ', MDL_V + WRITE(*,*) 'mdl_v__exp__2 = ', MDL_V__EXP__2 + WRITE(*,*) 'mdl_lam = ', MDL_LAM + WRITE(*,*) 'mdl_yb = ', MDL_YB + WRITE(*,*) 'mdl_yt = ', MDL_YT + WRITE(*,*) 'mdl_ytau = ', MDL_YTAU + WRITE(*,*) 'mdl_muH = ', MDL_MUH + WRITE(*,*) 'mdl_AxialZUp = ', MDL_AXIALZUP + WRITE(*,*) 'mdl_AxialZDown = ', MDL_AXIALZDOWN + WRITE(*,*) 'mdl_VectorZUp = ', MDL_VECTORZUP + WRITE(*,*) 'mdl_VectorZDown = ', MDL_VECTORZDOWN + WRITE(*,*) 'mdl_VectorWmDxU = ', MDL_VECTORWMDXU + WRITE(*,*) 'mdl_AxialWmDxU = ', MDL_AXIALWMDXU + WRITE(*,*) 'mdl_VectorWpUxD = ', MDL_VECTORWPUXD + WRITE(*,*) 'mdl_AxialWpUxD = ', MDL_AXIALWPUXD + WRITE(*,*) 'mdl_I1x33 = ', MDL_I1X33 + WRITE(*,*) 'mdl_I2x33 = ', MDL_I2X33 + WRITE(*,*) 'mdl_I3x33 = ', MDL_I3X33 + WRITE(*,*) 'mdl_I4x33 = ', MDL_I4X33 + WRITE(*,*) 'mdl_Vector_tbGp = ', MDL_VECTOR_TBGP + WRITE(*,*) 'mdl_Axial_tbGp = ', MDL_AXIAL_TBGP + WRITE(*,*) 'mdl_Vector_tbGm = ', MDL_VECTOR_TBGM + WRITE(*,*) 'mdl_Axial_tbGm = ', MDL_AXIAL_TBGM + WRITE(*,*) 'mdl_gw__exp__2 = ', MDL_GW__EXP__2 + WRITE(*,*) 'mdl_cw__exp__2 = ', MDL_CW__EXP__2 + WRITE(*,*) 'mdl_sw__exp__2 = ', MDL_SW__EXP__2 + WRITE(*,*) 'mdl_yb__exp__2 = ', MDL_YB__EXP__2 + WRITE(*,*) 'mdl_yt__exp__2 = ', MDL_YT__EXP__2 + WRITE(*,*) ' Internal Params evaluated point by point' + WRITE(*,*) ' ----------------------------------------' + WRITE(*,*) ' ' + WRITE(*,*) 'mdl_sqrt__aS = ', MDL_SQRT__AS + WRITE(*,*) 'mdl_G__exp__4 = ', MDL_G__EXP__4 + WRITE(*,*) 'mdl_G__exp__2 = ', MDL_G__EXP__2 + WRITE(*,*) 'mdl_G_UVg_1EPS_ = ', MDL_G_UVG_1EPS_ + WRITE(*,*) 'mdl_G_UVb_1EPS_ = ', MDL_G_UVB_1EPS_ + WRITE(*,*) 'mdl_tMass_UV_1EPS_ = ', MDL_TMASS_UV_1EPS_ + WRITE(*,*) 'mdl_G__exp__3 = ', MDL_G__EXP__3 + WRITE(*,*) 'mdl_MU_R__exp__2 = ', MDL_MU_R__EXP__2 + WRITE(*,*) 'mdl_G_UVb_FIN_ = ', MDL_G_UVB_FIN_ + WRITE(*,*) 'mdl_G_UVt_FIN_ = ', MDL_G_UVT_FIN_ + WRITE(*,*) 'mdl_tMass_UV_FIN_ = ', MDL_TMASS_UV_FIN_ diff --git a/UNITTEST_proc/Source/MODEL/printout.f b/UNITTEST_proc/Source/MODEL/printout.f new file mode 100644 index 0000000000..5b578a9c25 --- /dev/null +++ b/UNITTEST_proc/Source/MODEL/printout.f @@ -0,0 +1,40 @@ +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +c written by the UFO converter +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc + +c************************************************************************ +c** ** +c** MadGraph/MadEvent Interface to FeynRules ** +c** ** +c** C. Duhr (Louvain U.) - M. Herquet (NIKHEF) ** +c** ** +c************************************************************************ + + subroutine printout + use model_object + implicit none + + + include 'coupl.inc' ! needs VECSIZE_MEMMAX (defined in vector.inc) + include 'input.inc' + + include 'formats.inc' + + write(*,*) '*****************************************************' + write(*,*) '* MadGraph/MadEvent *' + write(*,*) '* -------------------------------- *' + write(*,*) '* http://madgraph.hep.uiuc.edu *' + write(*,*) '* http://madgraph.phys.ucl.ac.be *' + write(*,*) '* http://madgraph.roma2.infn.it *' + write(*,*) '* -------------------------------- *' + write(*,*) '* *' + write(*,*) '* PARAMETER AND COUPLING VALUES *' + write(*,*) '* *' + write(*,*) '*****************************************************' + write(*,*) + + include 'param_write.inc' + include 'coupl_write.inc' + + return + end diff --git a/UNITTEST_proc/Source/MODEL/rw_para.f b/UNITTEST_proc/Source/MODEL/rw_para.f new file mode 100644 index 0000000000..b1e7a382e0 --- /dev/null +++ b/UNITTEST_proc/Source/MODEL/rw_para.f @@ -0,0 +1,97 @@ +c************************************************************************ +c** ** +c** MadGraph/MadEvent Interface to FeynRules ** +c** ** +c** C. Duhr (Louvain U.) - M. Herquet (NIKHEF) ** +c** ** +c************************************************************************ + + subroutine setpara(param_name) + use model_object + implicit none + + character*(*) param_name + logical readlha + + include 'coupl.inc' + include 'input.inc' + include 'model_functions.inc' + include 'mp_coupl.inc' + include 'mp_input.inc' + + integer maxpara + parameter (maxpara=5000) + + integer npara + character*20 param(maxpara),value(maxpara) + + logical updateloop + common /to_updateloop/updateloop + data updateloop /.true./ + + call LHA_loadcard(param_name,npara,param,value) + ! also loop parameters should be initialised here + if (updateloop) then + include 'param_read.inc' + call coup() + else + updateloop=.true. + include 'param_read.inc' + call coup() + updateloop=.false. + endif + return + + end + + subroutine setParamLog(OnOff) + + logical OnOff + logical WriteParamLog + data WriteParamLog/.TRUE./ + common/IOcontrol/WriteParamLog + + WriteParamLog = OnOff + + end + + subroutine setpara2(param_name) + implicit none + + character(512) param_name + + integer k + logical found + + character(512) ParamCardPath + common/ParamCardPath/ParamCardPath + + if (param_name(1:1).ne.' ') then + ! Save the basename of the param_card for the ident_card. + ! If no absolute path was used then this ParamCardPath + ! remains empty + ParamCardPath = '.' + k = LEN(param_name) + found = .False. + do while (k.ge.1.and..not.found) + if (param_name(k:k).eq.'/') then + found=.True. + endif + k=k-1 + enddo + if (k.ge.1) then + ParamCardPath(1:k)=param_name(1:k) + endif + call setpara(param_name) + endif + if (param_name(1:1).eq.'*') then + ! Dummy call to printout so that it is available in the + ! dynamic library for MadLoop BLHA2 + ! In principle the --whole-archive option of ld could be + ! used but it is not always supported + call printout() + call setParamLog(.True.) + endif + return + + end diff --git a/UNITTEST_proc/Source/MODEL/testprog.f b/UNITTEST_proc/Source/MODEL/testprog.f new file mode 100644 index 0000000000..32dc93e98c --- /dev/null +++ b/UNITTEST_proc/Source/MODEL/testprog.f @@ -0,0 +1,72 @@ +c************************************************************************ +c** ** +c** MadGraph/MadEvent Interface to FeynRules ** +c** ** +c** C. Duhr (Louvain U.) - M. Herquet (NIKHEF) ** +c** ** +c************************************************************************ + + program testprog + + call setpara('param_card.dat') + + + + call printout + + end + +c$$$c +c$$$c program testing the running. need to modify the makefile accordingly +c$$$c +c$$$ program testprog +c$$$ implicit none +c$$$c define the function that run alphas +c$$$ DOUBLE PRECISION ALPHAS +c$$$ EXTERNAL ALPHAS +c$$$c get the value of gs +c$$$ include '../coupl.inc' +c$$$c for initialization of the running +c$$$ include "../alfas.inc" +c$$$c include parameter from the run_card (usefull for the running) +c$$$ INCLUDE '../maxparticles.inc' +c$$$c INCLUDE '../run.inc' +c$$$c local +c$$$ integer i +c$$$ double precision mu,as +c$$$ +c$$$c +c$$$c Scales +c$$$c +c$$$ real*8 scale,scalefact,alpsfact,mue_ref_fixed,mue_over_ref +c$$$ logical fixed_ren_scale,fixed_fac_scale1, fixed_fac_scale2,fixed_couplings,hmult +c$$$ logical fixed_extra_scale +c$$$ integer ickkw,nhmult,asrwgtflavor, dynamical_scale_choice,ievo_eva +c$$$ +c$$$ common/to_scale/scale,scalefact,alpsfact, mue_ref_fixed, mue_over_ref, +c$$$ $ fixed_ren_scale,fixed_fac_scale1, fixed_fac_scale2, +c$$$ $ fixed_couplings, fixed_extra_scale,ickkw,nhmult,hmult,asrwgtflavor, +c$$$ $ dynamical_scale_choice +c$$$ +c$$$ +c$$$ +c$$$c read the param_card +c$$$ call setpara('param_card.dat') +c$$$c define your running for as... +c$$$ fixed_extra_scale = .false. +c$$$ asmz = G**2/(16d0*atan(1d0)) +c$$$ nloop = 2 +c$$$ MUE_OVER_REF = 1d0 +c$$$ +c$$$c loop for the running +c$$$ do i=1,200 +c$$$ scale = 10*i +c$$$ G = SQRT(4d0*PI*ALPHAS(scale)) +c$$$ call UPDATE_AS_PARAM() +c$$$ call printout +c$$$ enddo +c$$$ +c$$$ +c$$$ end +c$$$ +c$$$ diff --git a/UNITTEST_proc/Source/coupl.inc b/UNITTEST_proc/Source/coupl.inc new file mode 120000 index 0000000000..6f1ad911bc --- /dev/null +++ b/UNITTEST_proc/Source/coupl.inc @@ -0,0 +1 @@ +MODEL/coupl.inc \ No newline at end of file diff --git a/UNITTEST_proc/Source/make_opts b/UNITTEST_proc/Source/make_opts new file mode 100644 index 0000000000..38ad3a74fc --- /dev/null +++ b/UNITTEST_proc/Source/make_opts @@ -0,0 +1,132 @@ +DEFAULT_F2PY_COMPILER=f2py +DEFAULT_F_COMPILER=gfortran +MACFLAG=-mmacosx-version-min=10.7 +DEFAULT_CPP_COMPILER=clang +MG5AMC_VERSION=SpecifiedByMG5aMCAtRunTime +STDLIB=-lstdc++ +PYTHIA8_PATH=NotInstalled +STDLIB_FLAG= +#end_of_make_opts_variables + +BIASLIBDIR=../../../lib/ +BIASLIBRARY=libbias.$(libext) + +# Rest of the makefile +ifeq ($(origin FFLAGS),undefined) +FFLAGS= -w -fPIC +#FFLAGS+= -g -fbounds-check -ffpe-trap=invalid,zero,overflow,underflow,denormal -Wall +endif + +FFLAGS += $(GLOBAL_FLAG) + +# REMOVE MACFLAG IF NOT ON MAC OR FOR F2PY +UNAME := $(shell uname -s) +ifdef f2pymode +MACFLAG= +else +ifneq ($(UNAME), Darwin) +MACFLAG= +endif +endif + +# set the flag for dynamical library +ifeq ($(UNAME), Darwin) +DYNLIBFLAG=-dynamiclib +RPATHFLAG=-install_name @rpath/ +else +DYNLIBFLAG=-shared -fPIC +RPATHFLAG=-Wl,-soname, +endif + +ifeq ($(origin CXXFLAGS),undefined) +CXXFLAGS= -O $(STDLIB_FLAG) $(MACFLAG) +endif + +ifeq ($(origin CFLAGS),undefined) +CFLAGS= -O $(STDLIB_FLAG) $(MACFLAG) +endif + +# Set FC unless it's defined by an environment variable +ifeq ($(origin FC),default) +FC=$(DEFAULT_F_COMPILER) +endif +ifeq ($(origin F2PY), undefined) +F2PY=$(DEFAULT_F2PY_COMPILER) +endif + +# Increase the number of allowed charcters in a Fortran line +ifeq ($(FC), ftn) +FFLAGS+= -extend-source # for ifort type of compiler +else + VERS="$(shell $(FC) --version | grep ifort -i)" + ifeq ($(VERS), "") + FFLAGS+= -ffixed-line-length-132 + else + FFLAGS+= -extend-source # for ifort type of compiler + endif +endif + + +UNAME := $(shell uname -s) +ifeq ($(origin LDFLAGS), undefined) +LDFLAGS=$(STDLIB) $(MACFLAG) +endif + +# Options: dynamic, lhapdf +# Option dynamic + +ifeq ($(UNAME), Darwin) +dylibext=dylib +else +dylibext=so +endif + +ifdef dynamic +ifeq ($(UNAME), Darwin) +libext=dylib +FFLAGS+= -fno-common +LDFLAGS += -bundle +define CREATELIB +$(FC) -dynamiclib -undefined dynamic_lookup -o $(1) $(2) +endef +else +libext=so +FFLAGS+= -fPIC +LDFLAGS += -shared +define CREATELIB +$(FC) $(FFLAGS) $(LDFLAGS) -o $(1) $(2) +endef +endif +else +libext=a +define CREATELIB +$(AR) cru $(1) $(2) +ranlib $(1) +endef +endif + +# Option lhapdf + +ifneq ($(lhapdf),) + CXXFLAGS += $(shell $(lhapdf) --cppflags) + alfas_functions=alfas_functions_lhapdf + alfas_to_clean=alfas_functions.o + llhapdf+= $(shell $(lhapdf) --cflags --libs) -lLHAPDF +# check if we need to activate c++11 (for lhapdf6.2) + ifeq ($(origin CXX),default) + ifeq ($lhapdfversion$lhapdfsubversion,62) + CXX=$(DEFAULT_CPP_COMPILER) -std=c++11 + else + CXX=$(DEFAULT_CPP_COMPILER) + endif + endif +else + alfas_functions=alfas_functions + alfas_to_clean=alfas_functions_lhapdf.o + llhapdf= +endif + +# Helper function to check MG5 version +define CHECK_MG5AMC_VERSION +python -c 'import re; from distutils.version import StrictVersion; print StrictVersion("$(MG5AMC_VERSION)") >= StrictVersion("$(1)") if re.match("^[\d\.]+$$","$(MG5AMC_VERSION)") else True;' +endef diff --git a/UNITTEST_proc/Source/makefile b/UNITTEST_proc/Source/makefile new file mode 100644 index 0000000000..d3d3be516b --- /dev/null +++ b/UNITTEST_proc/Source/makefile @@ -0,0 +1,96 @@ +# Definitions + +LIBDIR= ../lib/ +BINDIR= ../bin/ +PDFDIR= ./PDF/ +PWD = $(shell pwd) +CUTTOOLSDIR= $(PWD)/CutTools/ +IREGIDIR= ./IREGI/src/ + +include make_opts + +# Source files + +PROCESS= hfill.o matrix.o myamp.o +HBOOK = hfill.o hcurve.o hbook1.o hbook2.o +GENERIC = $(alfas_functions).o transpole.o invarients.o hfill.o pawgraphs.o ran1.o \ + rw_events.o rw_routines.o kin_functions.o open_file.o basecode.o setrun.o \ + run_printout.o dgauss.o readgrid.o getissud.o +INCLUDEF= coupl.inc genps.inc hbook.inc DECAY/decay.inc psample.inc cluster.inc sudgrid.inc +BANNER = write_banner.o rw_events.o ranmar.o kin_functions.o open_file.o rw_routines.o alfas_functions.o +COMBINE = combine_events.o rw_events.o ranmar.o kin_functions.o open_file.o rw_routines.o alfas_functions.o setrun.o +GENSUDGRID = gensudgrid.o is-sud.o setrun_gen.o rw_routines.o open_file.o + +# Locally compiled libraries + +LIBRARIES= $(LIBDIR)libcts.a $(LIBDIR)libiregi.a + +# Compile commands + +all: $(LIBRARIES) $(LIBDIR)libdhelas.$(libext) $(LIBDIR)libmodel.$(libext) +# Libraries +$(LIBDIR)libdhelas.$(libext): DHELAS + cd DHELAS; make +$(LIBDIR)libmodel.$(libext): MODEL + cd MODEL; make + +CutTools: $(LIBDIR)libcts.a +libcuttools: $(LIBDIR)libcts.a + +IREGI: $(LIBDIR)libiregi.a +libiregi: $(LIBDIR)libiregi.a + +$(LIBDIR)libcts.a: $(CUTTOOLSDIR) + cd $(CUTTOOLSDIR); make + ln -sf ../Source/CutTools/includects/libcts.a $(LIBDIR)libcts.a + ln -sf ../Source/CutTools/includects/mpmodule.mod $(LIBDIR)mpmodule.mod + +$(LIBDIR)libiregi.a: $(IREGIDIR) + cd $(IREGIDIR); make + ln -sf ../Source/$(IREGIDIR)libiregi.a $(LIBDIR)libiregi.a + +cleanCT: + cd $(CUTTOOLSDIR); make clean; cd .. + +cleanIR: + cd $(IREGIDIR); make clean; cd .. + +libdhelas: $(LIBDIR)libdhelas.$(libext) + +libmodel: $(LIBDIR)libmodel.$(libext) + +treatCardsLoopNoInit: + echo "Card treatment not necessary in MadLoop standalone mode." + +# Binaries + +$(BINDIR)sum_html: sum_html.o + $(FC) $(FFLAGS) -o $@ $^ +$(BINDIR)gen_ximprove: gen_ximprove.o ranmar.o rw_routines.o open_file.o + $(FC) $(FFLAGS) -o $@ $^ +$(BINDIR)combine_events: $(COMBINE) $(LIBDIR)libmodel.$(libext) $(LIBDIR)libpdf.$(libext) + $(FC) $(FFLAGS) -o $@ $(COMBINE) -L$(LIBDIR) -lmodel -lpdf $(lhapdf) +$(BINDIR)gensudgrid: $(GENSUDGRID) $(LIBDIR)libpdf.$(libext) $(LIBDIR)libcernlib.$(libext) + $(FC) $(FFLAGS) -o $@ $(GENSUDGRID) -L$(LIBDIR) -lmodel -lpdf -lcernlib $(lhapdf) +$(BINDIR)combine_runs: combine_runs.o rw_events.o + $(FC) $(FFLAGS) -o $@ $^ + +# Dependencies + +dsample.o: dsample.f genps.inc +invarients.o: invarients.f genps.inc +setrun.o: setrun.f nexternal.inc leshouche.inc genps.inc +sum_html.o: sum_html.f genps.inc +gen_ximprove.o: gen_ximprove.f run_config.inc +combine_events.o: combine_events.f run_config.inc +select_events.o: select_events.f run_config.inc +setrun.o: setrun.f nexternal.inc leshouche.inc + +clean: + rm -f *.o + rm -f param_card.inc run_card.inc + cd MODEL; make clean; cd .. + cd DHELAS; make clean; cd .. + if [ -d $(CUTTOOLSDIR) ]; then cd $(CUTTOOLSDIR); make clean; cd ..; fi + if [ -d $(STDHEPDIR) ]; then cd $(STDHEPDIR); make clean; cd ..; fi + rm -f $(BINDIR)/combine_events $(BINDIR)/gen_ximprove diff --git a/UNITTEST_proc/SubProcesses/MadLoop5_resources/ML5_0_ColorDenomFactors.dat b/UNITTEST_proc/SubProcesses/MadLoop5_resources/ML5_0_ColorDenomFactors.dat new file mode 100644 index 0000000000..c06e5148e7 --- /dev/null +++ b/UNITTEST_proc/SubProcesses/MadLoop5_resources/ML5_0_ColorDenomFactors.dat @@ -0,0 +1,129 @@ +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +-1 3 3 +-1 3 3 +-1 3 3 +-1 3 3 +1 -1 -1 +-1 1 1 +1 -1 -1 +-1 9 9 +1 -1 -1 +-1 9 9 +-1 9 9 +1 -1 -1 +-1 9 9 +1 -1 -1 +1 -1 -1 +-1 1 1 +-1 1 1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +-1 9 9 +-1 9 9 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +-1 9 9 +-1 9 9 +1 -1 -1 +1 -1 -1 +1 -1 -1 +-1 1 1 +-1 1 1 +-1 1 1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +1 -1 -1 +-1 3 3 +-1 3 3 +1 -1 -1 +-1 3 3 +-1 3 3 +1 -1 -1 +-1 3 3 +-1 3 3 diff --git a/UNITTEST_proc/SubProcesses/MadLoop5_resources/ML5_0_ColorNumFactors.dat b/UNITTEST_proc/SubProcesses/MadLoop5_resources/ML5_0_ColorNumFactors.dat new file mode 100644 index 0000000000..01be50116f --- /dev/null +++ b/UNITTEST_proc/SubProcesses/MadLoop5_resources/ML5_0_ColorNumFactors.dat @@ -0,0 +1,129 @@ +6 -3 3 +12 -6 6 +12 -6 6 +12 -6 6 +12 -6 6 +12 -6 6 +12 -6 6 +12 -6 6 +12 -6 6 +12 -6 6 +12 -6 6 +6 16 -2 +6 16 -2 +6 16 -2 +6 16 -2 +6 16 -2 +6 16 -2 +6 16 -2 +6 16 -2 +6 16 -2 +6 16 -2 +6 16 -2 +6 16 -2 +6 16 -2 +-6 -2 16 +-6 -2 16 +-6 -2 16 +-6 -2 16 +-6 -2 16 +-6 -2 16 +-6 -2 16 +-6 -2 16 +-6 -2 16 +-6 -2 16 +-6 -2 16 +-6 -2 16 +-6 -2 16 +-6 -2 16 +-6 -2 16 +-6 -2 16 +-6 -2 16 +-6 -2 16 +-6 -2 16 +-6 -2 16 +-6 -2 16 +-6 -2 16 +-6 -2 16 +6 16 -2 +6 16 -2 +6 16 -2 +6 16 -2 +6 16 -2 +6 16 -2 +6 16 -2 +6 16 -2 +6 16 -2 +6 16 -2 +12 -6 6 +12 -6 6 +12 -6 6 +12 -6 6 +12 -6 6 +12 -6 6 +12 -6 6 +12 -6 6 +12 -6 6 +12 -6 6 +6 -3 3 +6 -3 3 +6 -3 3 +6 -3 3 +12 -6 6 +12 -6 6 +12 -6 6 +12 -6 6 +6 -3 3 +12 -6 6 +6 -3 3 +12 -6 6 +12 -6 6 +12 -6 6 +6 16 -2 +6 16 -2 +-6 -2 16 +-6 -2 16 +-36 18 -18 +18 9 -9 +-2 1 -1 +8 64 -8 +9 -8 1 +-1 -8 1 +-8 -8 64 +9 -1 8 +1 1 -8 +-9 1 -8 +-9 8 -1 +-9 -9 0 +9 0 -9 +-18 9 -9 +36 -18 18 +18 -9 9 +-18 9 -9 +0 -1 -1 +1 1 -8 +-1 -8 1 +-36 18 -18 +-18 9 -9 +18 -9 9 +0 1 1 +-1 1 10 +1 10 1 +36 -18 18 +18 -9 9 +-18 9 -9 +-18 -9 9 +-9 0 9 +9 9 0 +36 -18 18 +-18 9 -9 +18 -9 9 +-6 3 -3 +3 2 -7 +-3 -7 2 +-6 3 -3 +3 2 -7 +-3 -7 2 +-6 3 -3 +3 2 -7 +-3 -7 2 diff --git a/UNITTEST_proc/SubProcesses/MadLoop5_resources/ML5_0_HelConfigs.dat b/UNITTEST_proc/SubProcesses/MadLoop5_resources/ML5_0_HelConfigs.dat new file mode 100644 index 0000000000..9bd09cc180 --- /dev/null +++ b/UNITTEST_proc/SubProcesses/MadLoop5_resources/ML5_0_HelConfigs.dat @@ -0,0 +1,16 @@ +-1 -1 -1 1 +-1 -1 -1 -1 +-1 -1 1 1 +-1 -1 1 -1 +-1 1 -1 1 +-1 1 -1 -1 +-1 1 1 1 +-1 1 1 -1 +1 -1 -1 1 +1 -1 -1 -1 +1 -1 1 1 +1 -1 1 -1 +1 1 -1 1 +1 1 -1 -1 +1 1 1 1 +1 1 1 -1 diff --git a/UNITTEST_proc/SubProcesses/MadLoop5_resources/MadLoopParams.dat b/UNITTEST_proc/SubProcesses/MadLoop5_resources/MadLoopParams.dat new file mode 120000 index 0000000000..e783cc88dd --- /dev/null +++ b/UNITTEST_proc/SubProcesses/MadLoop5_resources/MadLoopParams.dat @@ -0,0 +1 @@ +../MadLoopParams.dat \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/MadLoop5_resources/ident_card.dat b/UNITTEST_proc/SubProcesses/MadLoop5_resources/ident_card.dat new file mode 120000 index 0000000000..89e64bf2ef --- /dev/null +++ b/UNITTEST_proc/SubProcesses/MadLoop5_resources/ident_card.dat @@ -0,0 +1 @@ +../../Cards/ident_card.dat \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/MadLoop5_resources/param_card.dat b/UNITTEST_proc/SubProcesses/MadLoop5_resources/param_card.dat new file mode 120000 index 0000000000..44928ac167 --- /dev/null +++ b/UNITTEST_proc/SubProcesses/MadLoop5_resources/param_card.dat @@ -0,0 +1 @@ +../../Cards/param_card.dat \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/MadLoopCommons.f b/UNITTEST_proc/SubProcesses/MadLoopCommons.f new file mode 100644 index 0000000000..a97b549812 --- /dev/null +++ b/UNITTEST_proc/SubProcesses/MadLoopCommons.f @@ -0,0 +1,682 @@ + SUBROUTINE JOINPATH(STR1,STR2,PATH) + + CHARACTER*(*) STR1 + CHARACTER*(*) STR2 + CHARACTER*(*) PATH + + INTEGER I,J,K + + I =1 + DO WHILE (I.LE.LEN(STR1)) + IF(STR1(I:I).EQ.' ') GOTO 800 + PATH(I:I) = STR1(I:I) + I=I+1 + ENDDO + 800 CONTINUE + J=1 + DO WHILE (J.LE.LEN(STR2)) + IF(STR2(J:J).EQ.' ') GOTO 801 + PATH(I-1+J:I-1+J) = STR2(J:J) + J=J+1 + ENDDO + 801 CONTINUE + K=I+J-1 + DO WHILE (K.LE.LEN(PATH)) + PATH(K:K) = ' ' + K=K+1 + ENDDO + + RETURN + + END + + + + SUBROUTINE SET_FORBID_HEL_DOUBLECHECK(ONOFF) +C +C Give the possibility to overwrite the value of MadLoopParams.dat +C for the helicity double checking. +C Make sure to call this subroutine before the first time you +C call MadLoop. +C + IMPLICIT NONE +C +C ARGUMENT +C + LOGICAL ONOFF +C +C GLOBAL VARIABLES +C + LOGICAL FORBID_HEL_DOUBLECHECK + DATA FORBID_HEL_DOUBLECHECK/.FALSE./ + COMMON/FORBID_HEL_DOUBLECHECK/FORBID_HEL_DOUBLECHECK +C ---------- +C BEGIN CODE +C ---------- + FORBID_HEL_DOUBLECHECK = ONOFF + END + + SUBROUTINE SETMADLOOPPATH(PATH) + + CHARACTER(512) PATH + CHARACTER(512) DUMMY + CHARACTER(512) EPATH ! path of the executable + INTEGER POS + CHARACTER(512) PREFIX,FPATH + CHARACTER(17) NAMETOCHECK + PARAMETER (NAMETOCHECK='MadLoopParams.dat') + + LOGICAL ML_INIT + DATA ML_INIT/.TRUE./ + COMMON/ML_INIT/ML_INIT + + LOGICAL CTINIT,TIRINIT,GOLEMINIT,SAMURAIINIT,NINJAINIT + $ ,COLLIERINIT + DATA CTINIT,TIRINIT,GOLEMINIT,SAMURAIINIT,NINJAINIT,COLLIERINIT + $ /.TRUE.,.TRUE.,.TRUE.,.TRUE.,.TRUE.,.TRUE./ + COMMON/REDUCTIONCODEINIT/CTINIT, TIRINIT, GOLEMINIT, SAMURAIINIT + $ , NINJAINIT, COLLIERINIT + + + CHARACTER(512) MLPATH + DATA MLPATH/'[[NA]]'/ + COMMON/MLPATH/MLPATH + + INTEGER I + +C Just a dummy call for LD to pick up this function +C when creating the BLHA2 dynamic library + DUMMY = ' ' + CALL SETPARA2(DUMMY) + + IF (LEN(PATH).GE.4 .AND. PATH(1:4).EQ.'auto') THEN + IF (MLPATH(1:6).EQ.'[[NA]]') THEN +C Try to automatically find the path + PREFIX='./' + CALL JOINPATH(PREFIX,NAMETOCHECK,FPATH) + OPEN(1, FILE=FPATH, ERR=1, STATUS='OLD',ACTION='READ') + MLPATH=PREFIX + GOTO 10 + 1 CONTINUE + CLOSE(1) + PREFIX='./MadLoop5_resources/' + CALL JOINPATH(PREFIX,NAMETOCHECK,FPATH) + OPEN(1, FILE=FPATH, ERR=2, STATUS='OLD',ACTION='READ') + MLPATH=PREFIX + GOTO 10 + 2 CONTINUE + CLOSE(1) + PREFIX='../MadLoop5_resources/' + CALL JOINPATH(PREFIX,NAMETOCHECK,FPATH) + OPEN(1, FILE=FPATH, ERR=3, STATUS='OLD',ACTION='READ') + MLPATH=PREFIX + GOTO 10 + 3 CONTINUE + CLOSE(1) +C +C Try to automatically find the path from the executable +C location +C particularly usefull in gridpack readonly mode +C + CALL GETARG(0,PATH) !path is the PATH to the madevent executable (either global or from launching directory) + POS = INDEX(PATH,'/',.TRUE.) + PREFIX = PATH(:POS) + CALL JOINPATH(PREFIX,NAMETOCHECK,FPATH) + WRITE(*,*) 'test', FPATH + OPEN(1, FILE=FPATH, ERR=4, STATUS='OLD',ACTION='READ') + MLPATH=PREFIX + GOTO 10 + 4 CONTINUE + CLOSE(1) + PREFIX= PREFIX // '/MadLoop5_resources/' + CALL JOINPATH(PREFIX,NAMETOCHECK,FPATH) + WRITE(*,*) 'test', FPATH + OPEN(1, FILE=FPATH, ERR=5, STATUS='OLD',ACTION='READ') + MLPATH=PREFIX + GOTO 10 + 5 CONTINUE + CLOSE(1) + PREFIX= PATH(:POS) // '/../MadLoop5_resources/' + CALL JOINPATH(PREFIX,NAMETOCHECK,FPATH) + WRITE(*,*) 'test', FPATH + OPEN(1, FILE=FPATH, ERR=6, STATUS='OLD',ACTION='READ') + MLPATH=PREFIX + GOTO 10 + 6 CONTINUE + CLOSE(1) + +C We could not automatically find the auxiliary files + WRITE(*,*) '===' + WRITE(*,*) 'ERROR: MadLoop5 could not automatically find the' + $ //' file MadLoopParams.dat.' + WRITE(*,*) '===' + WRITE(*,*) '(Try using ' + $ //' (before your first call to MadLoop) in order to set the' + $ //' directory where this file is located as well as other' + $ //' auxiliary files, such as _ColorNumFactors.dat,' + $ //' _ColorDenomFactors.dat, etc..)' + STOP + 10 CONTINUE + CLOSE(1) + RETURN + ENDIF + ELSE +C Use the one specified by the user +C Make sure there is a separator added + I =1 + DO WHILE (I.LE.LEN(PATH) .AND. PATH(I:I).NE.' ') + I=I+1 + ENDDO + IF (PATH(I-1:I-1).NE.'/') THEN + PATH(I:I) = '/' + ENDIF + MLPATH=PATH + ENDIF + +C Check that the FilePath set is correct + CALL JOINPATH(MLPATH,NAMETOCHECK,FPATH) + OPEN(1, FILE=FPATH, ERR=33, STATUS='OLD',ACTION='READ') + GOTO 11 + 33 CONTINUE + CLOSE(1) + WRITE(*,*) '===' + WRITE(*,*) 'ERROR: The MadLoop5 auxiliary files could not be' + $ //' found in ',MLPATH + WRITE(*,*) '===' + STOP + 11 CONTINUE + CLOSE(1) + + END + + INTEGER FUNCTION SET_RET_CODE_U(MLRED,DOING_QP,STABLE) +C +C This functions returns the value of U +C +C +C U == 0 +C Not stable. +C U == 1 +C Stable with CutTools in double precision. +C U == 2 +C Stable with PJFry++. +C U == 3 +C Stable with IREGI. +C U == 4 +C Stable with Golem95. +C U == 5 +C Stable with Samurai. +C U == 6 +C Stable with Ninja in double precision. +C U == 7 +C Stable with COLLIER. +C U == 8 +C Stable with Ninja in quadruple precision. +C U == 9 +C Stable with CutTools in quadruple precision. +C + IMPLICIT NONE +C +C CONSTANTS +C +C +C ARGUMENTS +C + INTEGER MLRED + LOGICAL DOING_QP,STABLE +C +C LOCAL VARIABLES +C +C +C FUNCTION +C +C +C BEGIN CODE +C + IF(.NOT.STABLE)THEN + SET_RET_CODE_U=0 + RETURN + ENDIF + IF(DOING_QP)THEN + IF(MLRED.EQ.1)THEN + SET_RET_CODE_U=9 + RETURN + ELSEIF(MLRED.EQ.6)THEN + SET_RET_CODE_U=8 + RETURN + ELSE + STOP 'Only CutTools and Ninja can use quardruple precision' + ENDIF + ENDIF + IF(MLRED.GE.1.AND.MLRED.LE.7)THEN + SET_RET_CODE_U=MLRED + ELSE + STOP 'Only CutTools, PJFry++, IREGI, Golem95, Samurai, Ninja' + $ //' and COLLIER are available' + ENDIF + END + + SUBROUTINE DETECT_LOOPLIB(LIBNUM,NLOOPLINE,RANK,COMPLEX_MASS + $ ,HAS_HEFT_VERTEX,MAX_SPIN_CONNECTED_TO_LOOP,LPASS) +C +C DETECT WHICH LOOP LIB PASSED +C + IMPLICIT NONE +C +C CONSTANTS +C +C +C ARGUMENTS +C + INTEGER LIBNUM,NLOOPLINE,RANK,MAX_SPIN_CONNECTED_TO_LOOP +C The argument HAS_HEFT_VERTEX is only to implement correctly +C CutTools limitation + LOGICAL COMPLEX_MASS,LPASS,HAS_HEFT_VERTEX +C +C LOCAL VARIABLES +C +C +C GLOBAL VARIABLES +C +C ---------- +C BEGIN CODE +C ---------- + IF(LIBNUM.EQ.1)THEN +C CutTools + CALL DETECT_CUTTOOLS(NLOOPLINE,RANK,COMPLEX_MASS + $ ,HAS_HEFT_VERTEX,MAX_SPIN_CONNECTED_TO_LOOP,LPASS) + ELSEIF(LIBNUM.EQ.2)THEN +C PJFry++ + CALL DETECT_PJFRY(NLOOPLINE,RANK,COMPLEX_MASS,LPASS) + ELSEIF(LIBNUM.EQ.3)THEN +C IREGI + CALL DETECT_IREGI(NLOOPLINE,RANK,COMPLEX_MASS,LPASS) + ELSEIF(LIBNUM.EQ.4)THEN +C Golem95 + CALL DETECT_GOLEM(NLOOPLINE,RANK,COMPLEX_MASS,LPASS) + ELSEIF(LIBNUM.EQ.5)THEN +C Samurai + CALL DETECT_SAMURAI(NLOOPLINE,RANK,COMPLEX_MASS,LPASS) + ELSEIF(LIBNUM.EQ.6)THEN +C Ninja + CALL DETECT_NINJA(NLOOPLINE,RANK,COMPLEX_MASS,LPASS) + ELSEIF(LIBNUM.EQ.7)THEN +C Collier + CALL DETECT_COLLIER(NLOOPLINE,RANK,COMPLEX_MASS,LPASS) + ELSE + STOP 'Only CutTools, PJFry++, IREGI, Golem95, Samurai, Ninja' + $ //' and COLLIER are available' + ENDIF + RETURN + END + + SUBROUTINE DETECT_CUTTOOLS(NLOOPLINE,RANK,COMPLEX_MASS + $ ,HAS_HEFT_VERTEX,MAX_SPIN_CONNECTED_TO_LOOP,LPASS) +C +C DETECT whether CUTTOOLS CAN BE USED OR NOT +C + IMPLICIT NONE + +C +C CONSTANTS +C +C +C ARGUMENTS +C + INTEGER NLOOPLINE,RANK + INTEGER MAX_SPIN_CONNECTED_TO_LOOP + LOGICAL COMPLEX_MASS,LPASS,HAS_HEFT_VERTEX +C +C LOCAL VARIABLES +C + INTEGER MAX_RANK +C ---------- +C BEGIN CODE +C ---------- + LPASS=.TRUE. +C The limit of 10 loop lines is just a parameter hardcoded in +C CutTools sources. +C It can easily be increased if necessary. +C Also in the presence of spin2 particles, RANK=NLOOPLINE+1 is not +C supported, +C or in general whenever the higher rank doesn't come from the +C Higgs effective vertex. + + IF (MAX_SPIN_CONNECTED_TO_LOOP.LE.3.AND.HAS_HEFT_VERTEX) THEN + MAX_RANK = NLOOPLINE+1 + ELSE + MAX_RANK = NLOOPLINE + ENDIF + + IF( (RANK.GT.MAX_RANK).OR.(NLOOPLINE.GT.10) ) THEN + LPASS=.FALSE. + ENDIF + + RETURN + END + + SUBROUTINE DETECT_SAMURAI(NLOOPLINE,RANK,COMPLEX_MASS,LPASS) +C +C DETECT whether Samurai CAN BE USED OR NOT +C + IMPLICIT NONE +C +C CONSTANTS +C +C +C ARGUMENTS +C + INTEGER NLOOPLINE,RANK + LOGICAL COMPLEX_MASS,LPASS +C +C LOCAL VARIABLES +C +C +C GLOBAL VARIABLES +C +C ---------- +C BEGIN CODE +C ---------- + LPASS=.TRUE. +C The limit of 8 loop lines is just a parameter hardcoded in +C Samurai sources. +C It can easily be increased if necessary. + IF((NLOOPLINE+1.LT.RANK).OR.(NLOOPLINE.GT.8)) THEN + LPASS=.FALSE. + ENDIF + RETURN + END + + SUBROUTINE DETECT_NINJA(NLOOPLINE,RANK,COMPLEX_MASS,LPASS) +C +C Detect whether Ninja can be used or not +C + IMPLICIT NONE +C +C CONSTANTS +C +C +C ARGUMENTS +C + INTEGER NLOOPLINE,RANK + LOGICAL COMPLEX_MASS,LPASS +C +C LOCAL VARIABLES +C +C +C GLOBAL VARIABLES +C +C ---------- +C BEGIN CODE +C ---------- + LPASS=.TRUE. +C The limit of rank 20 is just a parameter hardcoded in Ninja +C sources. +C It can easily be increased if necessary. + IF((NLOOPLINE+1.LT.RANK).OR.(RANK.GE.20)) THEN + LPASS=.FALSE. + ENDIF + RETURN + END + + SUBROUTINE DETECT_COLLIER(NLOOPLINE,RANK,COMPLEX_MASS,LPASS) +C +C ARGUMENTS +C + INTEGER NLOOPLINE,RANK + LOGICAL COMPLEX_MASS,LPASS +C +C COLLIER is not available in this output. This subroutine is +C dummy. +C + LPASS=.TRUE. + END + + SUBROUTINE DETECT_PJFRY(NLOOPLINE,RANK,COMPLEX_MASS,LPASS) +C +C DETECT whether PJFRY++ CAN BE USED OR NOT +C + IMPLICIT NONE +C +C CONSTANTS +C +C +C ARGUMENTS +C + INTEGER NLOOPLINE,RANK + LOGICAL COMPLEX_MASS,LPASS +C +C LOCAL VARIABLES +C +C +C GLOBAL VARIABLES +C +C ---------- +C BEGIN CODE +C ---------- + LPASS=.TRUE. + IF(NLOOPLINE.LT.RANK.OR.RANK.GT.5.OR.NLOOPLINE.GT.5.OR.COMPLEX_MA + $SS.OR.NLOOPLINE.EQ.1) THEN + LPASS=.FALSE. + ENDIF + RETURN + END + + SUBROUTINE DETECT_IREGI(NLOOPLINE,RANK,COMPLEX_MASS,LPASS) +C +C DETECT whether IREGI CAN BE USED OR NOT +C + IMPLICIT NONE +C +C CONSTANTS +C +C +C ARGUMENTS +C + INTEGER NLOOPLINE,RANK + LOGICAL COMPLEX_MASS,LPASS +C +C LOCAL VARIABLES +C +C +C GLOBAL VARIABLES +C +C ---------- +C BEGIN CODE +C ---------- +C Stability studies show that IREGI is completely unstable at rank +C 7 and above. + LPASS=.TRUE. + IF(NLOOPLINE.GE.8.OR.RANK.GE.7)LPASS=.FALSE. + RETURN + END + + SUBROUTINE DETECT_GOLEM(NLOOPLINE,RANK,COMPLEX_MASS,LPASS) +C +C DETECT whether Golem95 CAN BE USED OR NOT +C + IMPLICIT NONE +C +C CONSTANTS +C +C +C ARGUMENTS +C + INTEGER NLOOPLINE,RANK + LOGICAL COMPLEX_MASS,LPASS +C +C LOCAL VARIABLES +C +C +C GLOBAL VARIABLES +C +C ---------- +C BEGIN CODE +C ---------- + + LPASS=.TRUE. + IF(NLOOPLINE.GE.7.OR.RANK.GE.7.OR.NLOOPLINE.LE.1)LPASS=.FALSE. + IF(NLOOPLINE.LE.5.AND.RANK.GT.NLOOPLINE+1)LPASS=.FALSE. + IF(NLOOPLINE.EQ.6.AND.RANK.GT.NLOOPLINE)LPASS=.FALSE. + RETURN + END + +C Now some sorting related routines. Only to be used for small +C arrays since these are not the most optimized sorting algorithms. + +C ----------------------------------------------------------------- +C --- +C INTEGER FUNCTION FindMinimum(): +C This function returns the location of the minimum in the section +C between Start and End. +C ----------------------------------------------------------------- +C --- + + INTEGER FUNCTION FINDMINIMUM(X, MSTART, MEND) + IMPLICIT NONE + INTEGER MAXNREF_EVALS + PARAMETER (MAXNREF_EVALS=100) + DOUBLE PRECISION, DIMENSION(MAXNREF_EVALS), INTENT(IN) :: X + INTEGER, INTENT(IN) :: MSTART, MEND + INTEGER :: MINIMUM + INTEGER :: LOCATION + INTEGER :: I + + MINIMUM = X(MSTART) ! assume the first is the min + LOCATION = MSTART ! record its position + DO I = MSTART+1, MEND ! start with next elements + IF (X(I) < MINIMUM) THEN ! if x(i) less than the min? + MINIMUM = X(I) ! Yes, a new minimum found + LOCATION = I ! record its position + END IF + END DO + FINDMINIMUM = LOCATION ! return the position + END FUNCTION FINDMINIMUM + +C ----------------------------------------------------------------- +C --- +C SUBROUTINE Swap(): +C This subroutine swaps the values of its two formal arguments. +C ----------------------------------------------------------------- +C --- + + SUBROUTINE SWAP(A, B) + IMPLICIT NONE + REAL*8, INTENT(INOUT) :: A, B + REAL*8 :: TEMP + + TEMP = A + A = B + B = TEMP + END SUBROUTINE SWAP + +C ----------------------------------------------------------------- +C --- +C SUBROUTINE Sort(): +C This subroutine receives an array x() and sorts it into ascending +C order. +C ----------------------------------------------------------------- +C --- + + SUBROUTINE SORT(X, MSIZE) + IMPLICIT NONE + INTEGER MAXNREF_EVALS + PARAMETER (MAXNREF_EVALS=100) + REAL*8, DIMENSION(MAXNREF_EVALS), INTENT(INOUT) :: X + INTEGER, INTENT(IN) :: MSIZE + INTEGER :: I + INTEGER :: LOCATION + INTEGER :: FINDMINIMUM + DO I = 1, MSIZE-1 ! except for the last + LOCATION = FINDMINIMUM(X, I, MSIZE) ! find min from this to last + CALL SWAP(X(I), X(LOCATION)) ! swap this and the minimum + END DO + END SUBROUTINE SORT + +C ----------------------------------------------------------------- +C --- +C REAL*8 FUNCTION Median() : +C This function receives an array X of N entries, copies its value +C to a local array Temp(), sorts Temp() and computes the median. +C The returned value is of REAL type. +C ----------------------------------------------------------------- +C --- + + REAL*8 FUNCTION MEDIAN(X, N) + IMPLICIT NONE + INTEGER MAXNREF_EVALS + PARAMETER (MAXNREF_EVALS=100) + REAL*8, DIMENSION(MAXNREF_EVALS), INTENT(IN) :: X + INTEGER, INTENT(IN) :: N + REAL*8, DIMENSION(MAXNREF_EVALS) :: TEMP + INTEGER :: I + + DO I = 1, N ! make a copy + TEMP(I) = X(I) + END DO + CALL SORT(TEMP, N) ! sort the copy + IF (MOD(N,2) == 0) THEN ! compute the median + MEDIAN = (TEMP(N/2) + TEMP(N/2+1)) / 2.0D0 + ELSE + MEDIAN = TEMP(N/2+1) + END IF + END FUNCTION MEDIAN + + + SUBROUTINE PRINT_MADLOOP_BANNER() + + WRITE(*,*) ' ====================================================' + $ //'====================================== ' + WRITE(*,*) '{ ' + $ //' }' + WRITE(*,*) '{ '//CHAR(27)//'[32m'//' ' + $ //' '/ + $ /CHAR(27)//'[0m'//' }' + WRITE(*,*) '{ '//CHAR(27)//'[32m'//' ' + $ //' ,, '/ + $ /CHAR(27)//'[0m'//' }' + WRITE(*,*) '{ '//CHAR(27)//'[32m'//'`7MMM. ,MMF'/ + $ /CHAR(39)//' `7MM `7MMF'//CHAR(39)//' ' + $ //' '//CHAR(27)//'[0m'//' }' + WRITE(*,*) '{ '//CHAR(27)//'[32m'//' MMMb dPMM ' + $ //' MM MM '/ + $ /CHAR(27)//'[0m'//' }' + WRITE(*,*) '{ '//CHAR(27)//'[32m'//' M YM ,M MM ,6'/ + $ /CHAR(34)//'Yb. ,M'//CHAR(34)//''//CHAR(34)//'bMM MM ' + $ //' ,pW'//CHAR(34)//'Wq. ,pW'//CHAR(34)//'Wq.`7MMpdMAo. '/ + $ /CHAR(27)//'[0m'//' }' + WRITE(*,*) '{ '//CHAR(27)//'[32m'//' M Mb M'//CHAR(39)/ + $ /' MM 8) MM ,AP MM MM 6W'//CHAR(39)//' `Wb' + $ //' 6W'//CHAR(39)//' `Wb MM `Wb '//CHAR(27)//'[0m'//' ' + $ //' }' + WRITE(*,*) '{ '//CHAR(27)//'[32m'//' M YM.P'//CHAR(39)/ + $ /' MM ,pm9MM 8MI MM MM , 8M M8 8M M8 MM ' + $ //' M8 '//CHAR(27)//'[0m'//' }' + WRITE(*,*) '{ '//CHAR(27)//'[32m'//' M `YM'//CHAR(39)// + $ ' MM 8M MM `Mb MM MM ,M YA. ,A9 YA. ,A9 MM ' + $ //' ,AP '//CHAR(27)//'[0m'//' }' + WRITE(*,*) '{ '//CHAR(27)//'[32m'//'.JML. `'//CHAR(39)//' ' + $ //' .JMML.`Moo9^Yo.`Wbmd'//CHAR(34)//'MML..JMMmmmmMMM `Ybmd9'/ + $ /CHAR(39)//' `Ybmd9'//CHAR(39)//' MMbmmd'//CHAR(39)//' '/ + $ /CHAR(27)//'[0m'//' }' + WRITE(*,*) '{ '//CHAR(27)//'[32m'//' ' + $ //' MM '/ + $ /CHAR(27)//'[0m'//' }' + WRITE(*,*) '{ '//CHAR(27)//'[32m'//' ' + $ //' .JMML. '/ + $ /CHAR(27)//'[0m'//' }' + WRITE(*,*) '{ '//CHAR(27)//'[32m'//CHAR(27)//'[0m'/ + $ /'v3.7.2 (2026-04-29), Ref: arXiv:1103.0621v2, arXiv:1405.0301' + $ //CHAR(27)//'[32m'//' '//CHAR(27)//'[0m'//' ' + $ //' }' + WRITE(*,*) '{ '//CHAR(27)//'[32m'//' ' + $ //' '/ + $ /CHAR(27)//'[0m'//' }' + WRITE(*,*) '{ ' + $ //' }' + WRITE(*,*) ' ====================================================' + $ //'====================================== ' + + END + + diff --git a/UNITTEST_proc/SubProcesses/MadLoopParamReader.f b/UNITTEST_proc/SubProcesses/MadLoopParamReader.f new file mode 100644 index 0000000000..d8b4951a10 --- /dev/null +++ b/UNITTEST_proc/SubProcesses/MadLoopParamReader.f @@ -0,0 +1,343 @@ + subroutine MadLoopParamReader(filename, printParam) + + implicit none + + CHARACTER(512) fileName, buff, buff2, mode + CHARACTER*20 MLReductionLib_str,MLReductionLib_str_save + CHARACTER*2 MLReductionLib_char + INTEGER MLRed,i,j,k + + include "MadLoopParams.inc" + + logical printParam, couldRead, paramPrinted, find + data paramPrinted/.FALSE./ + couldRead=.False. +! Default parameters + + open(666, file=fileName, err=676, status='OLD', action='READ') + do + read(666,*,end=999) buff + if(index(buff,'#').eq.1) then + + if (buff .eq. '#CTModeInit') then + read(666,*,end=999) CTModeInit + if (CTModeInit .lt. 0 .or. + & CTModeInit .gt. 6 ) then + stop 'CTModeInit must be >= 0 and <=6.' + endif + + else if (buff .eq. '#CTModeRun') then + read(666,*,end=999) CTModeRun + if (CTModeRun .lt. -1 .or. + & CTModeRun .gt. 6 ) then + stop 'CTModeRun must be >= -1 and <=6.' + endif + + else if (buff .eq. '#COLLIERGlobalCache') then + read(666,*,end=999) COLLIERGlobalCache + if (COLLIERGlobalCache .lt. -1) then + stop 'COLLIERGlobalCache must be >= -1' + endif + + else if (buff .eq. '#NRotations_DP') then + read(666,*,end=999) NRotations_DP + if (NRotations_DP .lt. 0 .or. + & NRotations_DP .gt. 2 ) then + stop 'NRotations_DP must be >= 0 and <=2.' + endif + + else if (buff .eq. '#NRotations_QP') then + read(666,*,end=999) NRotations_QP + if (NRotations_QP .lt. 0 .or. + & NRotations_QP .gt. 2 ) then + stop 'NRotations_QP must be >= 0 and <=2.' + endif + + else if (buff .eq. '#MLStabThres') then + read(666,*,end=999) MLStabThres + if (MLStabThres.lt.0.0d0) then + stop 'MLStabThres must be >= 0' + endif + + else if (buff .eq. '#COLLIERRequiredAccuracy') then + read(666,*,end=999) COLLIERRequiredAccuracy + if (COLLIERRequiredAccuracy.le.0.0d0.and. + & COLLIERRequiredAccuracy.ne.-1.0d0) then + stop 'COLLIERRequiredAccuracy must be > 0 or = -1.0' + endif + + else if (buff .eq. '#CTLoopLibrary') then + read(666,*,end=999) CTLoopLibrary + if (CTLoopLibrary.lt.2 .or. + & CTLoopLibrary.gt.3) then + stop 'CTLoopLibrary must be >= 2 and <=3.' + endif + + else if (buff .eq. '#CTStabThres') then + read(666,*,end=999) CTStabThres + if (CTStabThres.le.0.0d0) then + stop 'CTStabThres must be > 0' + endif + + else if (buff .eq. '#ZeroThres') then + read(666,*,end=999) ZeroThres + if (ZeroThres.le.0.0d0) then + stop 'ZeroThres must be > 0' + endif + + else if (buff .eq. '#OSThres') then + read(666,*,end=999) OSThres + if (OSThres.le.0.0d0) then + stop 'OSThres must be > 0' + endif + + else if (buff .eq. '#CheckCycle') then + read(666,*,end=999) CheckCycle + if (CheckCycle.lt.1) then + stop 'CheckCycle must be >= 1' + endif + + else if (buff .eq. '#MaxAttempts') then + read(666,*,end=999) MaxAttempts + if (MaxAttempts.lt.1) then + stop 'MaxAttempts must be >= 1' + endif + + else if (buff .eq. '#COLLIERComputeUVpoles') then + read(666,*,end=999) COLLIERComputeUVpoles + + else if (buff .eq. '#COLLIERComputeIRpoles') then + read(666,*,end=999) COLLIERComputeIRpoles + + else if (buff .eq. '#COLLIERUseInternalStabilityTest') then + read(666,*,end=999) COLLIERUseInternalStabilityTest + + else if (buff .eq. '#COLLIERUseCacheForPoles') then + read(666,*,end=999) COLLIERUseCacheForPoles + + else if (buff .eq. '#COLLIERCanOutput') then + read(666,*,end=999) COLLIERCanOutput + + else if (buff .eq. '#UseLoopFilter') then + read(666,*,end=999) UseLoopFilter + + else if (buff .eq. '#DoubleCheckHelicityFilter') then + read(666,*,end=999) DoubleCheckHelicityFilter + + else if (buff .eq. '#LoopInitStartOver') then + read(666,*,end=999) LoopInitStartOver + + else if (buff .eq. '#HelInitStartOver') then + read(666,*,end=999) HelInitStartOver + + else if (buff .eq. '#WriteOutFilters') then + read(666,*,end=999) WriteOutFilters + + else if (buff .eq. '#UseQPIntegrandForNinja') then + read(666,*,end=999) UseQPIntegrandForNinja + + else if (buff .eq. '#UseQPIntegrandForCutTools') then + read(666,*,end=999) UseQPIntegrandForCutTools + + else if (buff .eq. '#ImprovePSPoint') then + read(666,*,end=999) ImprovePSPoint + if (ImprovePSPoint .lt. -1 .or. + & ImprovePSPoint .gt. 2 ) then + stop 'ImprovePSPoint must be >= -1 and <=2.' + endif + + else if (buff .eq. '#HelicityFilterLevel') then + read(666,*,end=999) HelicityFilterLevel + if (HelicityFilterLevel .lt. 0 .or. + & HelicityFilterLevel .gt. 2 ) then + stop 'HelicityFilterLevel must be >= 0 and <=2.' + endif + + else if (buff .eq. '#MLReductionLib') then + read(666,*,end=999) MLReductionLib_str + MLReductionLib(1:7)=0 + MLReductionLib_str_save=MLReductionLib_str + j=0 + DO + i=index(MLReductionLib_str,'|') + IF(i.EQ.0)THEN + MLReductionLib_char=MLReductionLib_str + ELSE + MLReductionLib_char=MLReductionLib_str(:i-1) + ENDIF + IF(MLReductionLib_char.EQ.'1 ')THEN + MLRed=1 + ELSEIF(MLReductionLib_char.EQ.'2 ')THEN + MLRed=2 + ELSEIF(MLReductionLib_char.EQ.'3 ')THEN + MLRed=3 + ELSEIF(MLReductionLib_char.EQ.'4 ')THEN + MLRed=4 + ELSEIF(MLReductionLib_char.EQ.'5 ')THEN + MLRed=5 + ELSEIF(MLReductionLib_char.EQ.'6 ')THEN + MLRed=6 + ELSEIF(MLReductionLib_char.EQ.'7 ')THEN + MLRed=7 + ELSE + PRINT *, 'MLReductionLib is wrong: '// + $ TRIM(MLReductionLib_str_save) + STOP + ENDIF + find=.FALSE. + DO k=1,j + IF(MLReductionLib(k).EQ.MLRed)THEN + find=.TRUE. + EXIT + ENDIF + ENDDO + IF(.NOT.find)THEN + j=j+1 + MLReductionLib(j)=MLRed + ENDIF + IF(i.EQ.0)THEN + EXIT + ELSE + MLReductionLib_str=MLReductionLib_str(i+1:) + ENDIF + ENDDO + else if (buff .eq. '#COLLIERMode') then + read(666,*,end=999) COLLIERMode + if (COLLIERMode .lt. 1 .or. + & COLLIERMode .gt.3) then + stop 'COLLIERMode must be >=1 and <=3.' + endif + else if (buff .eq. '#IREGIRECY') then + read(666,*,end=999) IREGIRECY + else if (buff .eq. '#IREGIMODE') then + read(666,*,end=999) IREGIMODE + if (IREGIMODE .lt. 0 .or. + & IREGIMODE .gt.2) then + stop 'IREGIMODE must be >=0 and <=2.' + endif + else + write(*,*) 'The parameter name ',buff(2:), + &' is not reckognized.' + stop + endif + + endif + enddo + 999 continue + couldRead=.True. + goto 998 + + 676 continue + write(*,*) '##E00 Error:: MadLoop parameter file ',fileName, + &' could not be found or is malformed. Please specify it.' + stop +C Below is the code if one desires to let the code continue with +C a non existing or malformed parameter file + write(*,*) '##I01 INFO :: The file ',fileName,' could not be ', + & ' open or did not contain the necessary information. The ', + & ' default MadLoop parameters will be used.' + call DefaultParam() + goto 999 + + 998 continue + + if(printParam.and..not.paramPrinted) then + write(*,*) + & '===============================================================' + if (couldRead) then + write(*,*) 'INFO: MadLoop read these parameters from ' + &,filename + else + write(*,*) 'INFO: MadLoop used the default parameters.' + endif + write(*,*) + & '===============================================================' + write(*,*) ' > MLReductionLib = ' + $ //TRIM(MLReductionLib_str_save) + write(*,*) ' > CTModeRun = ',CTModeRun + write(*,*) ' > MLStabThres = ',MLStabThres + write(*,*) ' > NRotations_DP = ',NRotations_DP + write(*,*) ' > NRotations_QP = ',NRotations_QP + write(*,*) ' > CTStabThres = ',CTStabThres + write(*,*) ' > CTLoopLibrary = ',CTLoopLibrary + write(*,*) ' > CTModeInit = ',CTModeInit + write(*,*) ' > CheckCycle = ',CheckCycle + write(*,*) ' > MaxAttempts = ',MaxAttempts + write(*,*) ' > UseLoopFilter = ',UseLoopFilter + write(*,*) ' > HelicityFilterLevel = ',HelicityFilterLevel + write(*,*) ' > ImprovePSPoint = ',ImprovePSPoint + write(*,*) ' > DoubleCheckHelicityFilter = ', + &DoubleCheckHelicityFilter + write(*,*) ' > LoopInitStartOver = ',LoopInitStartOver + write(*,*) ' > HelInitStartOver = ',HelInitStartOver + write(*,*) ' > ZeroThres = ',ZeroThres + write(*,*) ' > OSThres = ',OSThres + write(*,*) ' > WriteOutFilters = ',WriteOutFilters + write(*,*) ' > UseQPIntegrandForNinja = ', + &UseQPIntegrandForNinja + write(*,*) ' > UseQPIntegrandForCutTools = ', + &UseQPIntegrandForCutTools + write(*,*) ' > IREGIMODE = ',IREGIMODE + write(*,*) ' > IREGIRECY = ',IREGIRECY + write(*,*) ' > COLLIERMode = ',COLLIERMode + write(*,*) ' > COLLIERRequiredAccuracy = ', + $COLLIERRequiredAccuracy + write(*,*) ' > COLLIERCanOutput = ',COLLIERCanOutput + write(*,*) ' > COLLIERComputeUVpoles = ',COLLIERComputeUVpoles + write(*,*) ' > COLLIERComputeIRpoles = ',COLLIERComputeIRpoles + write(*,*) ' > COLLIERGlobalCache = ',COLLIERGlobalCache + write(*,*) ' > COLLIERUseCacheForPoles = ', + &COLLIERUseCacheForPoles + write(*,*) ' > COLLIERUseInternalStabilityTest = ', + &COLLIERUseInternalStabilityTest + write(*,*) + & '===============================================================' + paramPrinted=.TRUE. + endif + + close(666) + + end + + subroutine DefaultParam() + + implicit none + + include "MadLoopParams.inc" + + MLReductionLib(1)=6 + MLReductionLib(2)=7 + MLReductionLib(3)=1 + MLReductionLib(4:7)=0 + IREGIMODE=2 + IREGIRECY=.TRUE. + COLLIERComputeIRpoles = .TRUE. + COLLIERComputeUVpoles = .TRUE. + COLLIERUseCacheForPoles = .FALSE. + COLLIERCanOutput = .FALSE. + COLLIERGlobalCache = -1 + COLLIERMode=1 + COLLIERRequiredAccuracy=1.0d-8 + COLLIERUseInternalStabilityTest = .TRUE. + CTModeInit=0 + CTModeRun=-1 + NRotations_DP=0 + NRotations_QP=0 + MLStabThres=1.0d-3 + CTStabThres=1.0d-2 + CTLoopLibrary=3 + CheckCycle=3 + MaxAttempts=10 + HelicityFilterLevel=2 + UseLoopFilter=.False. + DoubleCheckHelicityFilter=.True. + LoopInitStartOver=.False. + HelInitStartOver=.False. + WriteOutFilters=.True. + ZeroThres=1.0d-9 + OSThres=1.0d-13 + ImprovePSPoint=2 + UseQPIntegrandForCutTools=.True. + UseQPIntegrandForNinja=.True. + + end diff --git a/UNITTEST_proc/SubProcesses/MadLoopParams.dat b/UNITTEST_proc/SubProcesses/MadLoopParams.dat new file mode 120000 index 0000000000..bf9bac2770 --- /dev/null +++ b/UNITTEST_proc/SubProcesses/MadLoopParams.dat @@ -0,0 +1 @@ +../Cards/MadLoopParams.dat \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/MadLoopParams.inc b/UNITTEST_proc/SubProcesses/MadLoopParams.inc new file mode 100644 index 0000000000..008576b237 --- /dev/null +++ b/UNITTEST_proc/SubProcesses/MadLoopParams.inc @@ -0,0 +1,30 @@ +!==================================================================== +! +! Define common block with all general parameters used by MadLoop +! See their definitions in the file MadLoopParams.dat +! +!==================================================================== +! + integer CTModeInit,CTModeRun,CheckCycle,MaxAttempts, + &CTLoopLibrary,NRotations_DP,NRotations_QP,ImprovePSPoint, + &MLReductionLib(8),IREGIMODE,HelicityFilterLevel,COLLIERMode, + &COLLIERGlobalCache + + real*8 MLStabThres,CTStabThres,ZeroThres,OSThres,COLLIERRequiredAccuracy + + logical UseLoopFilter,LoopInitStartOver,DoubleCheckHelicityFilter, + &COLLIERComputeIRpoles,COLLIERComputeUVpoles,COLLIERCanOutput + logical HelInitStartOver,IREGIRECY,WriteOutFilters + logical UseQPIntegrandForNinja, UseQPIntegrandForCutTools + logical COLLIERUseCacheForPoles,COLLIERUseInternalStabilityTest + + common /MADLOOP/CTModeInit,CTModeRun,NRotations_DP,NRotations_QP, + &COLLIERMode,COLLIERGlobalCache, + &ImprovePSPoint,CheckCycle, MaxAttempts,UseLoopFilter,MLStabThres, + &COLLIERRequiredAccuracy, + &CTStabThres,CTLoopLibrary,LoopInitStartOver, + &COLLIERComputeIRpoles,COLLIERComputeUVpoles,COLLIERCanOutput, + &COLLIERUseCacheForPoles,COLLIERUseInternalStabilityTest, + &DoubleCheckHelicityFilter,ZeroThres,OSThres,HelInitStartOver, + &MLReductionLib,IREGIMODE,HelicityFilterLevel,IREGIRECY, + &WriteOutFilters,UseQPIntegrandForNinja,UseQPIntegrandForCutTools diff --git a/UNITTEST_proc/SubProcesses/MadLoop_makefile_definitions b/UNITTEST_proc/SubProcesses/MadLoop_makefile_definitions new file mode 100644 index 0000000000..85078693a1 --- /dev/null +++ b/UNITTEST_proc/SubProcesses/MadLoop_makefile_definitions @@ -0,0 +1,13 @@ +LINK_LOOP_LIBS = -L$(LIBDIR) -lcts +LOOP_LIBS = $(LIBDIR)libcts.$(libext) +DYLOOP_LIBS = +LOOP_INCLUDE = +LOOP_PREFIX = P +DOTO = %.o +DOTF = %.f +LINK_MADLOOP_LIB = -L$(LIBDIR) -lMadLoop +MADLOOP_LIB = $(LIBDIR)libMadLoop.$(libext) +RPATH_LIBS = + +$(MADLOOP_LIB): + cd ..; make -f makefile_MadLoop OLP_static diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/CT_interface.f b/UNITTEST_proc/SubProcesses/P0_gg_ttx/CT_interface.f new file mode 100644 index 0000000000..600104f556 --- /dev/null +++ b/UNITTEST_proc/SubProcesses/P0_gg_ttx/CT_interface.f @@ -0,0 +1,663 @@ + SUBROUTINE ML5_0_CTLOOP(NLOOPLINE,PL,M2L,RANK,RES,STABLE) +C +C Generated by MadGraph5_aMC@NLO v. 3.7.2, 2026-04-29 +C By the MadGraph5_aMC@NLO Development Team +C Visit launchpad.net/madgraph5 and amcatnlo.web.cern.ch +C +C Interface between MG5 and CutTools. +C +C Process: g g > t t~ QCD<=2 QED=0 [ virt = QCD ] +C +C +C CONSTANTS +C + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + LOGICAL CHECKPCONSERVATION + PARAMETER (CHECKPCONSERVATION=.TRUE.) + REAL*8 NORMALIZATION + PARAMETER (NORMALIZATION = 1.D0/(16.D0*3.14159265358979323846D0* + $ *2)) +C +C ARGUMENTS +C + INTEGER NLOOPLINE, RANK + REAL*8 PL(0:3,NLOOPLINE) + REAL*8 PCT(0:3,0:NLOOPLINE-1) + COMPLEX*16 M2L(NLOOPLINE) + COMPLEX*16 M2LCT(0:NLOOPLINE-1) + COMPLEX*16 RES(3) + LOGICAL STABLE +C +C LOCAL VARIABLES +C + COMPLEX*16 R1, ACC + INTEGER I, J, K + LOGICAL CTINIT, TIRINIT, GOLEMINIT, SAMURAIINIT, NINJAINIT + COMMON/REDUCTIONCODEINIT/CTINIT,TIRINIT,GOLEMINIT,SAMURAIINIT + $ ,NINJAINIT +C +C EXTERNAL FUNCTIONS +C + EXTERNAL ML5_0_LOOPNUM + EXTERNAL ML5_0_MPLOOPNUM +C +C GLOBAL VARIABLES +C + INCLUDE 'coupl.inc' + INTEGER CTMODE + REAL*8 LSCALE + COMMON/ML5_0_CT/LSCALE,CTMODE + + INTEGER WE(NEXTERNAL) + INTEGER ID, SYMFACT, MULTIPLIER, AMPLNUM + COMMON/ML5_0_LOOP/WE,ID,SYMFACT, MULTIPLIER, AMPLNUM + +C ---------- +C BEGIN CODE +C ---------- + +C INITIALIZE CUTTOOLS IF NEEDED + IF (CTINIT) THEN + CTINIT=.FALSE. + CALL ML5_0_INITCT() + CALL CITE('Ossola:2007ax','one-loop reduction with CutTools') + ENDIF + +C YOU CAN FIND THE DETAILS ABOUT THE DIFFERENT CTMODE AT THE +C BEGINNING OF THE FILE CTS_CUTS.F90 IN THE CUTTOOLS DISTRIBUTION + +C CONVERT THE MASSES TO BE COMPLEX + DO I=1,NLOOPLINE + M2LCT(I-1)=M2L(I) + ENDDO + +C CONVERT THE MOMENTA FLOWING IN THE LOOP LINES TO CT CONVENTIONS + DO I=0,3 + DO J=0,(NLOOPLINE-1) + PCT(I,J)=0.D0 + ENDDO + ENDDO + DO I=0,3 + DO J=1,NLOOPLINE + PCT(I,0)=PCT(I,0)+PL(I,J) + ENDDO + ENDDO + IF (CHECKPCONSERVATION) THEN + IF (PCT(0,0).GT.1.D-6) THEN + WRITE(*,*) 'energy is not conserved ',PCT(0,0) + STOP 'energy is not conserved' + ELSEIF (PCT(1,0).GT.1.D-6) THEN + WRITE(*,*) 'px is not conserved ',PCT(1,0) + STOP 'px is not conserved' + ELSEIF (PCT(2,0).GT.1.D-6) THEN + WRITE(*,*) 'py is not conserved ',PCT(2,0) + STOP 'py is not conserved' + ELSEIF (PCT(3,0).GT.1.D-6) THEN + WRITE(*,*) 'pz is not conserved ',PCT(3,0) + STOP 'pz is not conserved' + ENDIF + ENDIF + DO I=0,3 + DO J=1,(NLOOPLINE-1) + DO K=1,J + PCT(I,J)=PCT(I,J)+PL(I,K) + ENDDO + ENDDO + ENDDO + + CALL CTSXCUT(CTMODE,LSCALE,MU_R,NLOOPLINE,ML5_0_LOOPNUM + $ ,ML5_0_MPLOOPNUM,RANK,PCT,M2LCT,RES,ACC,R1,STABLE) + RES(1)=NORMALIZATION*2.0D0*DBLE(RES(1)) + RES(2)=NORMALIZATION*2.0D0*DBLE(RES(2)) + RES(3)=NORMALIZATION*2.0D0*DBLE(RES(3)) +C WRITE(*,*) 'Loop AMPLNUM',AMPLNUM,' =',RES(1),RES(2),RES(3) + END + + SUBROUTINE ML5_0_INITCT() +C +C INITIALISATION OF CUTTOOLS +C +C LOCAL VARIABLES +C + REAL*8 THRS + LOGICAL EXT_NUM_FOR_R1 +C +C GLOBAL VARIABLES +C + INCLUDE 'MadLoopParams.inc' +C ---------- +C BEGIN CODE +C ---------- + +C DEFAULT PARAMETERS FOR CUTTOOLS +C ------------------------------- +C THRS1 IS THE PRECISION LIMIT BELOW WHICH THE MP ROUTINES +C ACTIVATES + THRS=CTSTABTHRES +C LOOPLIB SET WHAT LIBRARY CT USES +C 1 -> LOOPTOOLS +C 2 -> AVH +C 3 -> QCDLOOP + LOOPLIB=CTLOOPLIBRARY +C MADLOOP'S NUMERATOR IN THE DEFAULT OUTPUT IS SLOWER THAN THE +C RECONSTRUCTED ONE IN CT. SO WE BETTER USE CT ONE IN THIS CASE. + EXT_NUM_FOR_R1=.TRUE. +C ------------------------------- + +C The initialization below is for CT v1.8.+ + CALL CTSINIT(THRS,LOOPLIB,EXT_NUM_FOR_R1) +C The initialization below is for the older stable CT v1.7, still +C used for now in the beta release. +C CALL CTSINIT(THRS,LOOPLIB) + + END + + SUBROUTINE ML5_0_LOOP_2_2( LID, W1, W2, M1,MP_M1, M2,MP_M2, C1 + $ ,MP_C1, C2,MP_C2, RANK, LSYMFACT, LMULTIPLIER, AMPLN, RES, + $ STABLE) + USE ALOHA_OBJECT + + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INTEGER MAXLCOUPLINGS + PARAMETER (MAXLCOUPLINGS=4) + INTEGER NLOOPLINE + PARAMETER (NLOOPLINE=2) + INTEGER NWAVEFUNCS + PARAMETER (NWAVEFUNCS=10) + INTEGER NCOMB + PARAMETER (NCOMB=16) +C +C ARGUMENTS +C + INTEGER W1, W2 + COMPLEX*16 M1, M2 + COMPLEX*32 MP_M1, MP_M2 + COMPLEX*16 C1, C2 + COMPLEX*32 MP_C1, MP_C2 + + COMPLEX*16 RES(3) + INTEGER LID, RANK, LSYMFACT, LMULTIPLIER + INTEGER AMPLN + LOGICAL STABLE +C +C LOCAL VARIABLES +C + REAL*8 PL(0:3,NLOOPLINE) + COMPLEX*16 M2L(NLOOPLINE) + INTEGER PAIRING(NLOOPLINE) + INTEGER I, J, K, TEMP +C +C GLOBAL VARIABLES +C + INTEGER WE(NEXTERNAL) + INTEGER ID, SYMFACT, MULTIPLIER, AMPLNUM + COMMON/ML5_0_LOOP/WE,ID, SYMFACT, MULTIPLIER,AMPLNUM + + COMPLEX*16 LC(MAXLCOUPLINGS) + COMPLEX*16 ML(NEXTERNAL+2) + COMMON/ML5_0_DP_LOOP/LC,ML + + COMPLEX*32 MP_LC(MAXLCOUPLINGS) + COMPLEX*32 MP_ML(NEXTERNAL+2) + COMMON/ML5_0_MP_LOOP/MP_LC,MP_ML + + TYPE(ALOHA) W(NWAVEFUNCS,NCOMB) + INTEGER VALIDH + COMMON/ML5_0_WFCTS/W + COMMON/ML5_0_VALIDH/VALIDH + +C ---------- +C BEGIN CODE +C ---------- + + WE(1)=W1 + WE(2)=W2 + M2L(1)=M2**2 + M2L(2)=M1**2 + ML(1)=M2 + ML(2)=M2 + MP_ML(1)=MP_M2 + MP_ML(2)=MP_M2 + ML(3)=M1 + MP_ML(3)=MP_M1 + ML(4)=M2 + MP_ML(4)=MP_M2 + DO I=1,NLOOPLINE + PAIRING(I)=1 + ENDDO + + LC(1)=C1 + MP_LC(1)=MP_C1 + LC(2)=C2 + MP_LC(2)=MP_C2 + AMPLNUM=AMPLN + ID=LID + SYMFACT=LSYMFACT + MULTIPLIER=LMULTIPLIER + DO I=0,3 + TEMP=1 + DO J=1,NLOOPLINE + PL(I,J)=0.D0 + DO K=TEMP,(TEMP+PAIRING(J)-1) + PL(I,J)=PL(I,J)-W(WE(K),VALIDH)%P(I) + ENDDO + TEMP=TEMP+PAIRING(J) + ENDDO + ENDDO + CALL ML5_0_CTLOOP(NLOOPLINE,PL,M2L,RANK,RES,STABLE) + + END + + SUBROUTINE ML5_0_LOOP_3_3( LID, W1, W2, W3, M1,MP_M1, M2,MP_M2, + $ M3,MP_M3, C1,MP_C1, C2,MP_C2, C3,MP_C3, RANK, LSYMFACT, + $ LMULTIPLIER, AMPLN, RES, STABLE) + USE ALOHA_OBJECT + + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INTEGER MAXLCOUPLINGS + PARAMETER (MAXLCOUPLINGS=4) + INTEGER NLOOPLINE + PARAMETER (NLOOPLINE=3) + INTEGER NWAVEFUNCS + PARAMETER (NWAVEFUNCS=10) + INTEGER NCOMB + PARAMETER (NCOMB=16) +C +C ARGUMENTS +C + INTEGER W1, W2, W3 + COMPLEX*16 M1, M2, M3 + COMPLEX*32 MP_M1, MP_M2, MP_M3 + COMPLEX*16 C1, C2, C3 + COMPLEX*32 MP_C1, MP_C2, MP_C3 + + COMPLEX*16 RES(3) + INTEGER LID, RANK, LSYMFACT, LMULTIPLIER + INTEGER AMPLN + LOGICAL STABLE +C +C LOCAL VARIABLES +C + REAL*8 PL(0:3,NLOOPLINE) + COMPLEX*16 M2L(NLOOPLINE) + INTEGER PAIRING(NLOOPLINE) + INTEGER I, J, K, TEMP +C +C GLOBAL VARIABLES +C + INTEGER WE(NEXTERNAL) + INTEGER ID, SYMFACT, MULTIPLIER, AMPLNUM + COMMON/ML5_0_LOOP/WE,ID, SYMFACT, MULTIPLIER,AMPLNUM + + COMPLEX*16 LC(MAXLCOUPLINGS) + COMPLEX*16 ML(NEXTERNAL+2) + COMMON/ML5_0_DP_LOOP/LC,ML + + COMPLEX*32 MP_LC(MAXLCOUPLINGS) + COMPLEX*32 MP_ML(NEXTERNAL+2) + COMMON/ML5_0_MP_LOOP/MP_LC,MP_ML + + TYPE(ALOHA) W(NWAVEFUNCS,NCOMB) + INTEGER VALIDH + COMMON/ML5_0_WFCTS/W + COMMON/ML5_0_VALIDH/VALIDH + +C ---------- +C BEGIN CODE +C ---------- + + WE(1)=W1 + WE(2)=W2 + WE(3)=W3 + M2L(1)=M3**2 + M2L(2)=M1**2 + M2L(3)=M2**2 + ML(1)=M3 + ML(2)=M3 + MP_ML(1)=MP_M3 + MP_ML(2)=MP_M3 + ML(3)=M1 + MP_ML(3)=MP_M1 + ML(4)=M2 + MP_ML(4)=MP_M2 + ML(5)=M3 + MP_ML(5)=MP_M3 + DO I=1,NLOOPLINE + PAIRING(I)=1 + ENDDO + + LC(1)=C1 + MP_LC(1)=MP_C1 + LC(2)=C2 + MP_LC(2)=MP_C2 + LC(3)=C3 + MP_LC(3)=MP_C3 + AMPLNUM=AMPLN + ID=LID + SYMFACT=LSYMFACT + MULTIPLIER=LMULTIPLIER + DO I=0,3 + TEMP=1 + DO J=1,NLOOPLINE + PL(I,J)=0.D0 + DO K=TEMP,(TEMP+PAIRING(J)-1) + PL(I,J)=PL(I,J)-W(WE(K),VALIDH)%P(I) + ENDDO + TEMP=TEMP+PAIRING(J) + ENDDO + ENDDO + CALL ML5_0_CTLOOP(NLOOPLINE,PL,M2L,RANK,RES,STABLE) + + END + + SUBROUTINE ML5_0_LOOP_4_4( LID, W1, W2, W3, W4, M1,MP_M1, M2 + $ ,MP_M2, M3,MP_M3, M4,MP_M4, C1,MP_C1, C2,MP_C2, C3,MP_C3, C4 + $ ,MP_C4, RANK, LSYMFACT, LMULTIPLIER, AMPLN, RES, STABLE) + USE ALOHA_OBJECT + + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INTEGER MAXLCOUPLINGS + PARAMETER (MAXLCOUPLINGS=4) + INTEGER NLOOPLINE + PARAMETER (NLOOPLINE=4) + INTEGER NWAVEFUNCS + PARAMETER (NWAVEFUNCS=10) + INTEGER NCOMB + PARAMETER (NCOMB=16) +C +C ARGUMENTS +C + INTEGER W1, W2, W3, W4 + COMPLEX*16 M1, M2, M3, M4 + COMPLEX*32 MP_M1, MP_M2, MP_M3, MP_M4 + COMPLEX*16 C1, C2, C3, C4 + COMPLEX*32 MP_C1, MP_C2, MP_C3, MP_C4 + + COMPLEX*16 RES(3) + INTEGER LID, RANK, LSYMFACT, LMULTIPLIER + INTEGER AMPLN + LOGICAL STABLE +C +C LOCAL VARIABLES +C + REAL*8 PL(0:3,NLOOPLINE) + COMPLEX*16 M2L(NLOOPLINE) + INTEGER PAIRING(NLOOPLINE) + INTEGER I, J, K, TEMP +C +C GLOBAL VARIABLES +C + INTEGER WE(NEXTERNAL) + INTEGER ID, SYMFACT, MULTIPLIER, AMPLNUM + COMMON/ML5_0_LOOP/WE,ID, SYMFACT, MULTIPLIER,AMPLNUM + + COMPLEX*16 LC(MAXLCOUPLINGS) + COMPLEX*16 ML(NEXTERNAL+2) + COMMON/ML5_0_DP_LOOP/LC,ML + + COMPLEX*32 MP_LC(MAXLCOUPLINGS) + COMPLEX*32 MP_ML(NEXTERNAL+2) + COMMON/ML5_0_MP_LOOP/MP_LC,MP_ML + + TYPE(ALOHA) W(NWAVEFUNCS,NCOMB) + INTEGER VALIDH + COMMON/ML5_0_WFCTS/W + COMMON/ML5_0_VALIDH/VALIDH + +C ---------- +C BEGIN CODE +C ---------- + + WE(1)=W1 + WE(2)=W2 + WE(3)=W3 + WE(4)=W4 + M2L(1)=M4**2 + M2L(2)=M1**2 + M2L(3)=M2**2 + M2L(4)=M3**2 + ML(1)=M4 + ML(2)=M4 + MP_ML(1)=MP_M4 + MP_ML(2)=MP_M4 + ML(3)=M1 + MP_ML(3)=MP_M1 + ML(4)=M2 + MP_ML(4)=MP_M2 + ML(5)=M3 + MP_ML(5)=MP_M3 + ML(6)=M4 + MP_ML(6)=MP_M4 + DO I=1,NLOOPLINE + PAIRING(I)=1 + ENDDO + + LC(1)=C1 + MP_LC(1)=MP_C1 + LC(2)=C2 + MP_LC(2)=MP_C2 + LC(3)=C3 + MP_LC(3)=MP_C3 + LC(4)=C4 + MP_LC(4)=MP_C4 + AMPLNUM=AMPLN + ID=LID + SYMFACT=LSYMFACT + MULTIPLIER=LMULTIPLIER + DO I=0,3 + TEMP=1 + DO J=1,NLOOPLINE + PL(I,J)=0.D0 + DO K=TEMP,(TEMP+PAIRING(J)-1) + PL(I,J)=PL(I,J)-W(WE(K),VALIDH)%P(I) + ENDDO + TEMP=TEMP+PAIRING(J) + ENDDO + ENDDO + CALL ML5_0_CTLOOP(NLOOPLINE,PL,M2L,RANK,RES,STABLE) + + END + + SUBROUTINE ML5_0_LOOP_2_3_2( LID, P1, P2, W1, W2, W3, M1,MP_M1, + $ M2,MP_M2, C1,MP_C1, C2,MP_C2, RANK, LSYMFACT, LMULTIPLIER, + $ AMPLN, RES, STABLE) + USE ALOHA_OBJECT + + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INTEGER MAXLCOUPLINGS + PARAMETER (MAXLCOUPLINGS=4) + INTEGER NLOOPLINE + PARAMETER (NLOOPLINE=2) + INTEGER NWAVEFUNCS + PARAMETER (NWAVEFUNCS=10) + INTEGER NCOMB + PARAMETER (NCOMB=16) +C +C ARGUMENTS +C + INTEGER W1, W2, W3 + COMPLEX*16 M1, M2 + COMPLEX*32 MP_M1, MP_M2 + COMPLEX*16 C1, C2 + COMPLEX*32 MP_C1, MP_C2 + INTEGER P1, P2 + COMPLEX*16 RES(3) + INTEGER LID, RANK, LSYMFACT, LMULTIPLIER + INTEGER AMPLN + LOGICAL STABLE +C +C LOCAL VARIABLES +C + REAL*8 PL(0:3,NLOOPLINE) + COMPLEX*16 M2L(NLOOPLINE) + INTEGER PAIRING(NLOOPLINE) + INTEGER I, J, K, TEMP +C +C GLOBAL VARIABLES +C + INTEGER WE(NEXTERNAL) + INTEGER ID, SYMFACT, MULTIPLIER, AMPLNUM + COMMON/ML5_0_LOOP/WE,ID, SYMFACT, MULTIPLIER,AMPLNUM + + COMPLEX*16 LC(MAXLCOUPLINGS) + COMPLEX*16 ML(NEXTERNAL+2) + COMMON/ML5_0_DP_LOOP/LC,ML + + COMPLEX*32 MP_LC(MAXLCOUPLINGS) + COMPLEX*32 MP_ML(NEXTERNAL+2) + COMMON/ML5_0_MP_LOOP/MP_LC,MP_ML + + TYPE(ALOHA) W(NWAVEFUNCS,NCOMB) + INTEGER VALIDH + COMMON/ML5_0_WFCTS/W + COMMON/ML5_0_VALIDH/VALIDH + +C ---------- +C BEGIN CODE +C ---------- + + WE(1)=W1 + WE(2)=W2 + WE(3)=W3 + M2L(1)=M2**2 + M2L(2)=M1**2 + ML(1)=M2 + ML(2)=M2 + MP_ML(1)=MP_M2 + MP_ML(2)=MP_M2 + ML(3)=M1 + MP_ML(3)=MP_M1 + ML(4)=M2 + MP_ML(4)=MP_M2 + PAIRING(1)=P1 + PAIRING(2)=P2 + LC(1)=C1 + MP_LC(1)=MP_C1 + LC(2)=C2 + MP_LC(2)=MP_C2 + AMPLNUM=AMPLN + ID=LID + SYMFACT=LSYMFACT + MULTIPLIER=LMULTIPLIER + DO I=0,3 + TEMP=1 + DO J=1,NLOOPLINE + PL(I,J)=0.D0 + DO K=TEMP,(TEMP+PAIRING(J)-1) + PL(I,J)=PL(I,J)-W(WE(K),VALIDH)%P(I) + ENDDO + TEMP=TEMP+PAIRING(J) + ENDDO + ENDDO + CALL ML5_0_CTLOOP(NLOOPLINE,PL,M2L,RANK,RES,STABLE) + + END + + SUBROUTINE ML5_0_LOOP_3_4_3( LID, P1, P2, P3, W1, W2, W3, W4, M1 + $ ,MP_M1, M2,MP_M2, M3,MP_M3, C1,MP_C1, C2,MP_C2, C3,MP_C3, RANK + $ , LSYMFACT, LMULTIPLIER, AMPLN, RES, STABLE) + USE ALOHA_OBJECT + + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INTEGER MAXLCOUPLINGS + PARAMETER (MAXLCOUPLINGS=4) + INTEGER NLOOPLINE + PARAMETER (NLOOPLINE=3) + INTEGER NWAVEFUNCS + PARAMETER (NWAVEFUNCS=10) + INTEGER NCOMB + PARAMETER (NCOMB=16) +C +C ARGUMENTS +C + INTEGER W1, W2, W3, W4 + COMPLEX*16 M1, M2, M3 + COMPLEX*32 MP_M1, MP_M2, MP_M3 + COMPLEX*16 C1, C2, C3 + COMPLEX*32 MP_C1, MP_C2, MP_C3 + INTEGER P1, P2, P3 + COMPLEX*16 RES(3) + INTEGER LID, RANK, LSYMFACT, LMULTIPLIER + INTEGER AMPLN + LOGICAL STABLE +C +C LOCAL VARIABLES +C + REAL*8 PL(0:3,NLOOPLINE) + COMPLEX*16 M2L(NLOOPLINE) + INTEGER PAIRING(NLOOPLINE) + INTEGER I, J, K, TEMP +C +C GLOBAL VARIABLES +C + INTEGER WE(NEXTERNAL) + INTEGER ID, SYMFACT, MULTIPLIER, AMPLNUM + COMMON/ML5_0_LOOP/WE,ID, SYMFACT, MULTIPLIER,AMPLNUM + + COMPLEX*16 LC(MAXLCOUPLINGS) + COMPLEX*16 ML(NEXTERNAL+2) + COMMON/ML5_0_DP_LOOP/LC,ML + + COMPLEX*32 MP_LC(MAXLCOUPLINGS) + COMPLEX*32 MP_ML(NEXTERNAL+2) + COMMON/ML5_0_MP_LOOP/MP_LC,MP_ML + + TYPE(ALOHA) W(NWAVEFUNCS,NCOMB) + INTEGER VALIDH + COMMON/ML5_0_WFCTS/W + COMMON/ML5_0_VALIDH/VALIDH + +C ---------- +C BEGIN CODE +C ---------- + + WE(1)=W1 + WE(2)=W2 + WE(3)=W3 + WE(4)=W4 + M2L(1)=M3**2 + M2L(2)=M1**2 + M2L(3)=M2**2 + ML(1)=M3 + ML(2)=M3 + MP_ML(1)=MP_M3 + MP_ML(2)=MP_M3 + ML(3)=M1 + MP_ML(3)=MP_M1 + ML(4)=M2 + MP_ML(4)=MP_M2 + ML(5)=M3 + MP_ML(5)=MP_M3 + PAIRING(1)=P1 + PAIRING(2)=P2 + PAIRING(3)=P3 + LC(1)=C1 + MP_LC(1)=MP_C1 + LC(2)=C2 + MP_LC(2)=MP_C2 + LC(3)=C3 + MP_LC(3)=MP_C3 + AMPLNUM=AMPLN + ID=LID + SYMFACT=LSYMFACT + MULTIPLIER=LMULTIPLIER + DO I=0,3 + TEMP=1 + DO J=1,NLOOPLINE + PL(I,J)=0.D0 + DO K=TEMP,(TEMP+PAIRING(J)-1) + PL(I,J)=PL(I,J)-W(WE(K),VALIDH)%P(I) + ENDDO + TEMP=TEMP+PAIRING(J) + ENDDO + ENDDO + CALL ML5_0_CTLOOP(NLOOPLINE,PL,M2L,RANK,RES,STABLE) + + END + diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoop5_resources b/UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoop5_resources new file mode 120000 index 0000000000..6a87da9776 --- /dev/null +++ b/UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoop5_resources @@ -0,0 +1 @@ +../MadLoop5_resources \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoopCommons.f b/UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoopCommons.f new file mode 120000 index 0000000000..836e6d22fb --- /dev/null +++ b/UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoopCommons.f @@ -0,0 +1 @@ +../MadLoopCommons.f \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoopParamReader.f b/UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoopParamReader.f new file mode 120000 index 0000000000..fed1ffb18b --- /dev/null +++ b/UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoopParamReader.f @@ -0,0 +1 @@ +../MadLoopParamReader.f \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoopParams.inc b/UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoopParams.inc new file mode 120000 index 0000000000..84aae98059 --- /dev/null +++ b/UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoopParams.inc @@ -0,0 +1 @@ +../MadLoopParams.inc \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/born_matrix.f b/UNITTEST_proc/SubProcesses/P0_gg_ttx/born_matrix.f new file mode 100644 index 0000000000..b9066b0d2e --- /dev/null +++ b/UNITTEST_proc/SubProcesses/P0_gg_ttx/born_matrix.f @@ -0,0 +1,989 @@ + SUBROUTINE ML5_0_SMATRIXHEL(P,HEL, FLAV_IDX, ANS) + IMPLICIT NONE +C +C CONSTANT +C + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INTEGER NCOMB + PARAMETER ( NCOMB=16) +CF2PY INTENT(OUT) :: ANS +CF2PY INTENT(IN) :: HEL +CF2PY INTENT(IN) :: P(0:3,NEXTERNAL) +CF2PY INTENT(IN) :: FLAV_IDX + +C +C ARGUMENTS +C + REAL*8 P(0:3,NEXTERNAL),ANS + INTEGER HEL + INTEGER FLAV_IDX +C +C GLOBAL VARIABLES +C + INTEGER USERHEL + COMMON/ML5_0_HELUSERCHOICE/USERHEL +C ---------- +C BEGIN CODE +C ---------- + USERHEL=HEL + CALL ML5_0_SMATRIX(P,FLAV_IDX,ANS) + USERHEL=-1 + + END + + SUBROUTINE ML5_0_SMATRIX(P, FLAV_IDX, ANS) +C +C Generated by MadGraph5_aMC@NLO v. 3.7.2, 2026-04-29 +C By the MadGraph5_aMC@NLO Development Team +C Visit launchpad.net/madgraph5 and amcatnlo.web.cern.ch +C +C MadGraph5_aMC@NLO StandAlone Version +C +C Returns amplitude squared summed/avg over colors +C and helicities +C for the point in phase space P(0:3,NEXTERNAL) +C +C Process: g g > t t~ QCD<=2 QED=0 [ virt = QCD ] +C + IMPLICIT NONE +C +C CONSTANTS +C + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INTEGER NINITIAL + PARAMETER (NINITIAL=2) + INTEGER NPOLENTRIES + PARAMETER (NPOLENTRIES=(NEXTERNAL+1)*6) + INTEGER NCOMB + PARAMETER ( NCOMB=16) + INTEGER HELAVGFACTOR + PARAMETER (HELAVGFACTOR=4) +C +C ARGUMENTS +C + REAL*8 P(0:3,NEXTERNAL),ANS +CF2PY INTENT(OUT) :: ANS +CF2PY INTENT(IN) :: P(0:3,NEXTERNAL) +CF2PY INTENT(IN) :: FLAV_IDX +C +C LOCAL VARIABLES +C + INTEGER NHEL(NEXTERNAL,NCOMB) +C put in common block to expose this variable to python interface + COMMON/ML5_0_PROCESS_NHEL/NHEL + REAL*8 T + REAL*8 ML5_0_MATRIX + INTEGER IHEL,IDEN, I, J +C For a 1>N process, them BEAMTWO_HELAVGFACTOR would be set to 1. + INTEGER BEAMS_HELAVGFACTOR(2) + DATA (BEAMS_HELAVGFACTOR(I),I=1,2)/2,2/ + INTEGER FLAVOR(NEXTERNAL) + INTEGER JC(NEXTERNAL) + INTEGER NFLAV + PARAMETER (NFLAV=1) + INTEGER NNTRY_FLAV, NGOODHEL_FLAV + PARAMETER (NNTRY_FLAV=NFLAV) + PARAMETER (NGOODHEL_FLAV=NCOMB*NFLAV) + INTEGER FLAV_IDX + INTEGER ML5_0_GET_FLAVOR_INDEX + INTEGER NTRY(NFLAV) + LOGICAL GOODHEL(NCOMB,NFLAV) + DATA NTRY/NNTRY_FLAV*0/ + DATA GOODHEL/NGOODHEL_FLAV*.FALSE./ + +C +C GLOBAL VARIABLES +C + INTEGER USERHEL + COMMON/ML5_0_HELUSERCHOICE/USERHEL + DATA USERHEL/-1/ + LOGICAL HELRESET + COMMON/ML5_0_HELRESET/HELRESET + DATA HELRESET/.TRUE./ + + DATA (NHEL(I, 1),I=1,4) /-1,-1,-1, 1/ + DATA (NHEL(I, 2),I=1,4) /-1,-1,-1,-1/ + DATA (NHEL(I, 3),I=1,4) /-1,-1, 1, 1/ + DATA (NHEL(I, 4),I=1,4) /-1,-1, 1,-1/ + DATA (NHEL(I, 5),I=1,4) /-1, 1,-1, 1/ + DATA (NHEL(I, 6),I=1,4) /-1, 1,-1,-1/ + DATA (NHEL(I, 7),I=1,4) /-1, 1, 1, 1/ + DATA (NHEL(I, 8),I=1,4) /-1, 1, 1,-1/ + DATA (NHEL(I, 9),I=1,4) / 1,-1,-1, 1/ + DATA (NHEL(I, 10),I=1,4) / 1,-1,-1,-1/ + DATA (NHEL(I, 11),I=1,4) / 1,-1, 1, 1/ + DATA (NHEL(I, 12),I=1,4) / 1,-1, 1,-1/ + DATA (NHEL(I, 13),I=1,4) / 1, 1,-1, 1/ + DATA (NHEL(I, 14),I=1,4) / 1, 1,-1,-1/ + DATA (NHEL(I, 15),I=1,4) / 1, 1, 1, 1/ + DATA (NHEL(I, 16),I=1,4) / 1, 1, 1,-1/ + DATA IDEN/256/ + + INTEGER POLARIZATIONS(0:NEXTERNAL,0:5) + COMMON/ML5_0_BORN_BEAM_POL/POLARIZATIONS + DATA ((POLARIZATIONS(I,J),I=0,NEXTERNAL),J=0,5)/NPOLENTRIES*-1/ + +C +C FUNCTIONS +C + LOGICAL ML5_0_IS_BORN_HEL_SELECTED + INTEGER ML5_0_BROKEN_SYM +C ---------- +C Check if helreset mode is on +C --------- + IF (HELRESET) THEN + DO I=1,NFLAV + NTRY(I) = 0 + ENDDO + DO I=1,NCOMB + DO J=1,NFLAV + GOODHEL(I,J) = .FALSE. + ENDDO + ENDDO + HELRESET = .FALSE. + ENDIF + +C ---------- +C BEGIN CODE +C ---------- +C FLAV_IDX=0 (or out of range) means GET_FLAVOR_INDEX could not +C resolve +C the requested flavor: it is not an allowed combination, so its +C matrix +C element is identically zero. Short-circuit before touching the +C 1..NFLAV GOODHEL/NTRY arrays. + IF (FLAV_IDX.LT.1 .OR. FLAV_IDX.GT.NFLAV) THEN + ANS = 0D0 + RETURN + ENDIF + CALL ML5_0_GET_FLAVOR(FLAV_IDX, FLAVOR) + IF(USERHEL.EQ.-1) NTRY(FLAV_IDX)=NTRY(FLAV_IDX)+1 + DO IHEL=1,NEXTERNAL + JC(IHEL) = +1 + ENDDO +C When spin-2 particles are involved, the Helicity filtering is +C dangerous for the 2->1 topology. +C This is because depending on the MC setup the initial PS points +C have back-to-back initial states +C for which some of the spin-2 helicity configurations are zero. +C But they are no longer zero +C if the point is boosted on the z-axis. Remember that HELAS +C helicity amplitudes are no longer +C lorentz invariant with expternal spin-2 particles (only the +C helicity sum is). +C For this reason, we simply remove the filterin when there is +C only three external particles. + IF (NEXTERNAL.LE.3) THEN + DO IHEL=1,NCOMB + DO J=1,NFLAV + GOODHEL(IHEL,J)=.TRUE. + ENDDO + ENDDO + ENDIF + ANS = 0D0 + DO IHEL=1,NCOMB + IF (USERHEL.EQ.-1.OR.USERHEL.EQ.IHEL) THEN + IF (GOODHEL(IHEL,FLAV_IDX) .OR. NTRY(FLAV_IDX) .LT. + $ 20.OR.USERHEL.NE.-1) THEN + IF(NTRY(FLAV_IDX).GE.2.AND.POLARIZATIONS(0,0).NE. + $ -1.AND.(.NOT.ML5_0_IS_BORN_HEL_SELECTED(IHEL))) THEN + CYCLE + ENDIF + T=ML5_0_MATRIX(P ,NHEL(1,IHEL),JC(1),FLAV_IDX) + IF(POLARIZATIONS(0,0).EQ. + $ -1.OR.ML5_0_IS_BORN_HEL_SELECTED(IHEL)) THEN + ANS=ANS+T + ENDIF + IF (T .NE. 0D0 .AND. .NOT. GOODHEL(IHEL,FLAV_IDX)) THEN + GOODHEL(IHEL,FLAV_IDX)=.TRUE. + ENDIF + ENDIF + ENDIF + ENDDO + ANS=ANS/DBLE(IDEN)*ML5_0_BROKEN_SYM(FLAVOR) + IF(USERHEL.NE.-1) THEN + ANS=ANS*HELAVGFACTOR + ELSE + DO J=1,NINITIAL + IF (POLARIZATIONS(J,0).NE.-1) THEN + ANS=ANS*BEAMS_HELAVGFACTOR(J) + ANS=ANS/POLARIZATIONS(J,0) + ENDIF + ENDDO + ENDIF + END + + + REAL*8 FUNCTION ML5_0_MATRIX(P,NHEL,IC,FLAV_IDX) + USE MODEL_OBJECT +C +C Generated by MadGraph5_aMC@NLO v. 3.7.2, 2026-04-29 +C By the MadGraph5_aMC@NLO Development Team +C Visit launchpad.net/madgraph5 and amcatnlo.web.cern.ch +C +C Returns amplitude squared -- no average over initial +C state/symmetry factor +C for the point with external lines W(0:6,NEXTERNAL) +C +C Process: g g > t t~ QCD<=2 QED=0 [ virt = QCD ] +C + USE ALOHA_OBJECT + IMPLICIT NONE +C +C CONSTANTS +C + INTEGER NGRAPHS + PARAMETER (NGRAPHS=3) + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INTEGER NWAVEFUNCS, NCOLOR + PARAMETER (NWAVEFUNCS=5, NCOLOR=2) + REAL*8 ZERO + PARAMETER (ZERO=0D0) + COMPLEX*16 IMAG1 + PARAMETER (IMAG1=(0D0,1D0)) +C +C ARGUMENTS +C + REAL*8 P(0:3,NEXTERNAL) + INTEGER NHEL(NEXTERNAL), IC(NEXTERNAL) + INTEGER FLAV_IDX +C +C LOCAL VARIABLES +C + INTEGER I,J + COMPLEX*16 ZTEMP + INTEGER CF_INDEX + INTEGER ML5_0_CF(3) + INTEGER ML5_0_DENOM + COMMON /ML5_0_COLOR_MATRIX/ ML5_0_CF,ML5_0_DENOM + COMPLEX*16 AMP(NGRAPHS), JAMP(NCOLOR), TMP_JAMP(0) + TYPE(ALOHA) W(NWAVEFUNCS) + COMPLEX*16 DUM0,DUM1 + DATA DUM0, DUM1/(0D0, 0D0), (1D0, 0D0)/ +C +C GLOBAL VARIABLES +C + INCLUDE 'coupl.inc' + +C COLOR DATA + DATA ML5_0_DENOM/3/ + DATA (ML5_0_CF(I),I= 1, 2) /16,-4/ +C 1 T(1,2,3,4) + DATA (ML5_0_CF(I),I= 3, 3) /16/ +C 1 T(2,1,3,4) +C +C +C ---------- +C BEGIN CODE +C ---------- + CALL ML5_0_GET_AMP(P,NHEL,IC,FLAV_IDX,AMP) +C WRITE (*,*) ' -> AMP = ', AMP + CALL ML5_0_GET_JAMP(AMP,JAMP) +C WRITE (*,*) ' -> JAMP = ', JAMP + CALL ML5_0_GET_MATRIX(JAMP,ML5_0_MATRIX) +C write (*,*) " -> col.ave. |M|^2 for HEL=[", NHEL ,"] = ", +C ML5_0_MATRIX + + + + END + + SUBROUTINE ML5_0_GET_NHEL(IDEN_STAR,NHEL_STAR) +C CONSTANTS +C +CF2PY INTENT(OUT) :: NHEL_STAR +CF2PY INTENT(OUT) :: IDEN_STAR + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INTEGER NCOMB + PARAMETER ( NCOMB=16) + + INTEGER NHEL(NEXTERNAL,NCOMB),NHEL_STAR(NEXTERNAL,NCOMB) + INTEGER IDEN,IDEN_STAR + + DATA (NHEL(I, 1),I=1,4) /-1,-1,-1, 1/ + DATA (NHEL(I, 2),I=1,4) /-1,-1,-1,-1/ + DATA (NHEL(I, 3),I=1,4) /-1,-1, 1, 1/ + DATA (NHEL(I, 4),I=1,4) /-1,-1, 1,-1/ + DATA (NHEL(I, 5),I=1,4) /-1, 1,-1, 1/ + DATA (NHEL(I, 6),I=1,4) /-1, 1,-1,-1/ + DATA (NHEL(I, 7),I=1,4) /-1, 1, 1, 1/ + DATA (NHEL(I, 8),I=1,4) /-1, 1, 1,-1/ + DATA (NHEL(I, 9),I=1,4) / 1,-1,-1, 1/ + DATA (NHEL(I, 10),I=1,4) / 1,-1,-1,-1/ + DATA (NHEL(I, 11),I=1,4) / 1,-1, 1, 1/ + DATA (NHEL(I, 12),I=1,4) / 1,-1, 1,-1/ + DATA (NHEL(I, 13),I=1,4) / 1, 1,-1, 1/ + DATA (NHEL(I, 14),I=1,4) / 1, 1,-1,-1/ + DATA (NHEL(I, 15),I=1,4) / 1, 1, 1, 1/ + DATA (NHEL(I, 16),I=1,4) / 1, 1, 1,-1/ + DATA IDEN/256/ + IDEN_STAR = IDEN + NHEL_STAR = NHEL + END + + SUBROUTINE ML5_0_GET_AMP(P,NHEL,IC,FLAV_IDX,AMP) + USE MODEL_OBJECT +C +C Process: g g > t t~ QCD<=2 QED=0 [ virt = QCD ] +C +CF2PY INTENT(OUT) :: AMP +CF2PY INTENT(IN) :: NHEL +CF2PY INTENT(IN) :: P(0:3,NEXTERNAL) +CF2PY INTENT(IN) :: IC +CF2PY INTENT(IN) :: FLAV_IDX + + USE ALOHA_OBJECT + IMPLICIT NONE +C +C CONSTANTS +C + INTEGER NGRAPHS + PARAMETER (NGRAPHS=3) + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INTEGER NWAVEFUNCS, NCOLOR + PARAMETER (NWAVEFUNCS=5, NCOLOR=2) + REAL*8 ZERO + PARAMETER (ZERO=0D0) +C +C ARGUMENTS +C + REAL*8 P(0:3,NEXTERNAL) + INTEGER NHEL(NEXTERNAL), IC(NEXTERNAL) + INTEGER FLAV_IDX + INTEGER FLAVOR(NEXTERNAL) +C +C LOCAL VARIABLES +C + COMPLEX*16 AMP(NGRAPHS) + TYPE(ALOHA) W(NWAVEFUNCS) + COMPLEX*16 DUM0,DUM1 + DATA DUM0, DUM1/(0D0, 0D0), (1D0, 0D0)/ + DOUBLE PRECISION BWCUTOFF +C Flavor table for the FLAV_IDX -> FLAVOR rebuild. + INTEGER NMASK_FLAV + PARAMETER (NMASK_FLAV=1) + INTEGER MASK_J + INTEGER FLAV_TABLE(NEXTERNAL, NMASK_FLAV) + DATA FLAV_TABLE / 1, 1, 1, 1 / +C +C GLOBAL VARIABLES +C + INCLUDE 'coupl.inc' + +C +C + BWCUTOFF=15 ! use if $ syntax is defined in the process +C Rebuild FLAVOR(NEXTERNAL) from the resolved flavor index. + IF (FLAV_IDX .GE. 1 .AND. FLAV_IDX .LE. NMASK_FLAV) THEN + DO MASK_J = 1, NEXTERNAL + FLAVOR(MASK_J) = FLAV_TABLE(MASK_J, FLAV_IDX) + ENDDO + ELSE + DO MASK_J = 1, NEXTERNAL + FLAVOR(MASK_J) = FLAV_TABLE(MASK_J, 1) + ENDDO + ENDIF + CALL VXXXXX(P(0,1),ZERO,NHEL(1),-1,W(1)) + CALL VXXXXX(P(0,2),ZERO,NHEL(2),-1,W(2)) + CALL OXXXXX(P(0,3),MDL_MT,NHEL(3),+1, FLAVOR(3),W(3)) + CALL IXXXXX(P(0,4),MDL_MT,NHEL(4),-1, FLAVOR(4),W(4)) + CALL VVV1P0_1(W(1),W(2),GC_4,ZERO,ZERO,W(5)) +C Amplitude(s) for diagram number 1 + CALL FFV1_0(W(4),W(3),W(5),GC_5,AMP(1)) + CALL FFV1_1(W(3),W(1),GC_5,MDL_MT,MDL_WT,W(5)) +C Amplitude(s) for diagram number 2 + CALL FFV1_0(W(4),W(5),W(2),GC_5,AMP(2)) + CALL FFV1_2(W(4),W(1),GC_5,MDL_MT,MDL_WT,W(5)) +C Amplitude(s) for diagram number 3 + CALL FFV1_0(W(5),W(3),W(2),GC_5,AMP(3)) + + END + + SUBROUTINE ML5_0_GET_JAMP(AMP,JAMP) +C +C Process: g g > t t~ QCD<=2 QED=0 [ virt = QCD ] +C +CF2PY INTENT(OUT) :: JAMP +CF2PY INTENT(IN) :: AMP + + IMPLICIT NONE +C +C CONSTANTS +C + INTEGER NGRAPHS + PARAMETER (NGRAPHS=3) + INTEGER NCOLOR + PARAMETER ( NCOLOR=2) + COMPLEX*16 IMAG1 + PARAMETER (IMAG1=(0D0,1D0)) + COMPLEX*16 AMP(NGRAPHS), JAMP(NCOLOR), TMP_JAMP(0) + + JAMP(1) = ((0.000000000000000D+00,1.000000000000000D+00))*AMP(1) + $ +(-1.000000000000000D+00)*AMP(2) + JAMP(2) = ((0.000000000000000D+00,-1.000000000000000D+00))*AMP(1) + $ +(-1.000000000000000D+00)*AMP(3) + END + + SUBROUTINE ML5_0_GET_MATRIX(JAMP,MATRIX) +C +C Process: g g > t t~ QCD<=2 QED=0 [ virt = QCD ] +C + IMPLICIT NONE +C +C CONSTANTS +C +CF2PY INTENT(OUT) :: MATRIX +CF2PY INTENT(IN) :: JAMP + + + INTEGER NCOLOR + PARAMETER (NCOLOR=2) + REAL*8 ZERO,MATRIX + PARAMETER (ZERO=0D0) +C + +C LOCAL VARIABLES +C + INTEGER I,J + COMPLEX*16 ZTEMP + + INTEGER CF_INDEX + INTEGER ML5_0_CF(NCOLOR*(NCOLOR+1)/2) + INTEGER ML5_0_DENOM + COMMON /ML5_0_COLOR_MATRIX/ ML5_0_CF,ML5_0_DENOM + COMPLEX*16 JAMP(NCOLOR), TMP_JAMP(0) + COMPLEX*16 DUM0,DUM1 + DATA DUM0, DUM1/(0D0, 0D0), (1D0, 0D0)/ +C + +C COLOR DATA +C + + MATRIX = 0.D0 + CF_INDEX = 0 + DO I = 1, NCOLOR + ZTEMP = (0.D0,0.D0) + DO J = I, NCOLOR + CF_INDEX = CF_INDEX + 1 + ZTEMP = ZTEMP + ML5_0_CF(CF_INDEX)*JAMP(J) + ENDDO + MATRIX = MATRIX+ZTEMP*DCONJG(JAMP(I))/ML5_0_DENOM + ENDDO + END + + + + SUBROUTINE ML5_0_GET_INTER(JAMP_1,JAMP_2, INTER) + +CF2PY INTENT(OUT) :: INTER +CF2PY INTENT(IN) :: JAMP_1 +CF2PY INTENT(IN) :: JAMP_2 + + INTEGER I,J + INTEGER NCOLOR + PARAMETER (NCOLOR=2) + INTEGER CF_INDEX + INTEGER ML5_0_CF(NCOLOR*(NCOLOR+1)/2) + INTEGER ML5_0_DENOM, IDEN + DATA IDEN/256/ + COMMON /ML5_0_COLOR_MATRIX/ ML5_0_CF,ML5_0_DENOM + COMPLEX*16 JAMP_1(NCOLOR),JAMP_2(NCOLOR),INTER + +C COLOR DATA +C + + INTER = (0.D0,0.D0) + CF_INDEX = 0 + DO I = 1, NCOLOR +C ZTEMP = DCONJG(JAMP_2(I)) + DO J=I, NCOLOR + CF_INDEX = CF_INDEX +1 + INTER = INTER + ML5_0_CF(CF_INDEX) * (JAMP_1(J) * + $ DCONJG(JAMP_2(I)) +JAMP_1(I) * DCONJG(JAMP_2(J))) + ENDDO + ENDDO + INTER = INTER/ (2D0*ML5_0_DENOM*IDEN) + + END + + + + SUBROUTINE ML5_0_GET_DENSITY(P, POS, N_CHANGING, ALLOW_HEL, + $ N_COMB, FLAVOR, ALPHAS, SCALE2, INTER) +C P momenta +C NHEL base of helicity that are not changing +C POS(N_CHNGING): position of the changing helicity +C n_changing: number of changing helicity +C ALLOW_HEL(NCOMB, N_CHANGING): combination of helicity to +C consider (all jamp computed) +C INTER(NCOMB*(NCOMB+1)/2): all interference term (not the +C symmetric one) + USE MODEL_OBJECT + IMPLICIT NONE +CF2PY INTENT(IN) :: P(0:3,4) +CF2PY INTENT(IN) :: POS(N_CHANGING) +CF2PY INTENT(IN) :: N_CHANGING +CF2PY INTENT(IN) :: ALLOW_HEL(N_CHANGING*N_COMB) +CF2PY INTENT(IN) :: N_COMB +CF2PY INTENT(IN) :: FLAVOR(4) +CF2PY INTENT(IN) :: ALPHAS +CF2PY INTENT(IN) :: SCALE2 +CF2PY INTENT(OUT) :: INTER(N_COMB*(N_COMB+1)/2) +C SCALE2 is a dummy argument added to have the same syntax as in +C loop-induced +C +C +C ARGUMENTS +C + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + REAL*8 P(0:3,NEXTERNAL) + INTEGER THISNHEL(NEXTERNAL) + INTEGER N_CHANGING, N_COMB + INTEGER POS(*) + INTEGER ALLOW_HEL(*) + INTEGER FLAVOR(NEXTERNAL) + DOUBLE PRECISION ALPHAS, SCALE2 + DOUBLE COMPLEX INTER(*) + INTEGER NINTER + INTEGER NB_NHEL + DOUBLE COMPLEX, ALLOCATABLE :: TMP_INTER(:) + PARAMETER (NB_NHEL=16) +C LOCAL + INTEGER I,IHEL,IPART + DOUBLE PRECISION PI +C + INTEGER NHEL(NEXTERNAL,NB_NHEL) +C put in common block to expose this variable to python interface + COMMON/ML5_0_PROCESS_NHEL/NHEL +C +C include coupling definition to update the value of alphas +C + INCLUDE 'coupl.inc' + + NINTER = N_COMB*(N_COMB+1)/2 + ALLOCATE(TMP_INTER(NINTER)) + TMP_INTER(:) = (0D0, 0D0) + + DO I=1, N_COMB*(N_COMB+1)/2 + INTER(I) = 0 + ENDDO + + IF (ALPHAS.NE.0D0) THEN + PI = 3.141592653589793D0 + G = 2* DSQRT(ALPHAS*PI) + CALL UPDATE_AS_PARAM() + ENDIF + DO IHEL =1, NB_NHEL + THISNHEL(:) = NHEL(:, IHEL) + DO IPART=1,N_CHANGING + IF(THISNHEL(POS(IPART)).NE.ALLOW_HEL(IPART)) GOTO 10 !BYPASS COMPUTATION FOR HELICITY + ENDDO + TMP_INTER(:) = 0 + CALL ML5_0_GET_ALL_INTER(P, THISNHEL, POS, N_CHANGING, + $ ALLOW_HEL, N_COMB, FLAVOR, TMP_INTER) + DO I = 1, N_COMB*(N_COMB+1)/2 + INTER(I) = INTER(I) + TMP_INTER(I) + ENDDO + 10 ENDDO + RETURN + DEALLOCATE(TMP_INTER) + END + + SUBROUTINE ML5_0_GET_ALL_INTER(P, NHEL, POS, N_CHANGING, + $ ALLOW_HEL, N_COMB, FLAVOR, INTER) +C P momenta +C NHEL base of helicity that are not changing +C POS(N_CHNGING): position of the changing helicity +C n_changing: number of changing helicity +C ALLOW_HEL(NCOMB, N_CHANGING): combination of helicity to +C consider (all jamp computed) +C INTER((NCOMB*NCOMB+1)/2: all interference term (not the +C symmetric one) + IMPLICIT NONE +CF2PY INTENT(IN) :: P(0:3,4) +CF2PY INTENT(IN) :: NHEL(4) +CF2PY INTENT(IN) :: POS(N_CHANGING) +CF2PY INTENT(IN) :: N_CHANGING +CF2PY INTENT(IN) :: ALLOW_HEL(N_CHANGING*N_COMB) +CF2PY INTENT(IN) :: N_COMB +CF2PY INTENT(IN) :: FLAVOR(4) +CF2PY INTENT(OUT) :: INTER(NCOMB*(NCOMB+1)/2) +C +C +C ARGUMENTS +C + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + REAL*8 P(0:3,NEXTERNAL) + INTEGER NHEL(NEXTERNAL) + INTEGER N_CHANGING, N_COMB + INTEGER POS(*) + INTEGER ALLOW_HEL(*) + INTEGER FLAVOR(NEXTERNAL) + DOUBLE COMPLEX INTER(*) +C +C Intermediate array +C + INTEGER NGRAPHS + PARAMETER (NGRAPHS=3) + INTEGER NCOLOR + PARAMETER (NCOLOR=2) + INTEGER IC(NEXTERNAL) + + DOUBLE COMPLEX AMP(NGRAPHS) + DOUBLE COMPLEX, ALLOCATABLE, SAVE :: JAMP(:,:) + INTEGER, SAVE :: S_NCOMB = 0 + +C +C LOCAL +C + INTEGER I,J,SOL,N + INTEGER FLAV_IDX + INTEGER ML5_0_GET_FLAVOR_INDEX + + IF (ALLOCATED(JAMP) .AND. S_NCOMB.NE.N_COMB) THEN + DEALLOCATE(JAMP) + ENDIF + + IF (.NOT.ALLOCATED(JAMP)) THEN + S_NCOMB=N_COMB + ALLOCATE(JAMP(NCOLOR, N_COMB)) + ENDIF +C ---------- +C BEGIN CODE +C ---------- + IC(:)=1 + FLAV_IDX = ML5_0_GET_FLAVOR_INDEX(FLAVOR) +C Unresolved flavor (not an allowed combination): the matrix +C element and +C therefore all interference terms are zero. + IF (FLAV_IDX.EQ.0) THEN + DO I = 1, N_COMB*(N_COMB+1)/2 + INTER(I) = (0D0, 0D0) + ENDDO + RETURN + ENDIF + DO I = 1, N_COMB + DO N = 1, N_CHANGING + NHEL(POS(N)) = ALLOW_HEL((I-1)*N_CHANGING+N) + ENDDO + CALL ML5_0_GET_AMP(P,NHEL,IC,FLAV_IDX,AMP) + CALL ML5_0_GET_JAMP(AMP,JAMP(1,I)) + ENDDO + + SOL = 0 + DO I = 1, N_COMB + DO J= I, N_COMB + SOL = SOL +1 + CALL ML5_0_GET_INTER(JAMP(1,I), JAMP(1,J), INTER(SOL)) + ENDDO + ENDDO + + + RETURN + END + + + + + SUBROUTINE ML5_0_GET_VALUE(P, ALPHAS, NHEL, FLAVOR ,ANS) +C f2py interface accepting the full FLAVOR(NEXTERNAL) array +C (back-compat): +C resolve it to FLAV_IDX and forward to GET_value_internal. Use +C GET_value_idx below to pass the flavor index directly. + USE MODEL_OBJECT + IMPLICIT NONE +C +C CONSTANT +C + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) +C +C ARGUMENTS +C + REAL*8 P(0:3,NEXTERNAL),ANS + INTEGER NHEL + DOUBLE PRECISION ALPHAS + INTEGER FLAVOR(NEXTERNAL) + INTEGER FLAV_IDX + INTEGER ML5_0_GET_FLAVOR_INDEX +CF2PY INTENT(OUT) :: ANS +CF2PY INTENT(IN) :: NHEL +CF2PY INTENT(IN) :: P(0:3,NEXTERNAL) +CF2PY INTENT(IN) :: ALPHAS +CF2PY INTENT(IN) :: FLAVOR(NEXTERNAL) +C ROUTINE FOR F2PY to read the benchmark point. + + FLAV_IDX = ML5_0_GET_FLAVOR_INDEX(FLAVOR) + CALL ML5_0_GET_VALUE_INTERNAL(P, ALPHAS, NHEL, FLAV_IDX ,ANS) + RETURN + END + + + SUBROUTINE ML5_0_GET_VALUE_IDX(P, ALPHAS, NHEL, FLAV_IDX ,ANS) +C f2py interface accepting the flavor index directly. + USE MODEL_OBJECT + IMPLICIT NONE +C +C CONSTANT +C + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) +C +C ARGUMENTS +C + REAL*8 P(0:3,NEXTERNAL),ANS + INTEGER NHEL + DOUBLE PRECISION ALPHAS + INTEGER FLAV_IDX +CF2PY INTENT(OUT) :: ANS +CF2PY INTENT(IN) :: NHEL +CF2PY INTENT(IN) :: P(0:3,NEXTERNAL) +CF2PY INTENT(IN) :: ALPHAS +CF2PY INTENT(IN) :: FLAV_IDX + + CALL ML5_0_GET_VALUE_INTERNAL(P, ALPHAS, NHEL, FLAV_IDX ,ANS) + RETURN + END + + + SUBROUTINE ML5_0_GET_VALUE_INTERNAL(P, ALPHAS, NHEL, FLAV_IDX + $ ,ANS) + USE MODEL_OBJECT +C This routine is the real value but can not be in the interface +C due to f2py not knowing how to handle the couplings common block + USE MODEL_OBJECT + IMPLICIT NONE +C +C CONSTANT +C + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) +C +C ARGUMENTS +C + REAL*8 P(0:3,NEXTERNAL),ANS + INTEGER NHEL + DOUBLE PRECISION ALPHAS + REAL*8 PI + INTEGER FLAV_IDX +C ROUTINE FOR F2PY to read the benchmark point. +C the include file with the values of the parameters and masses + INCLUDE 'coupl.inc' + + PI = 3.141592653589793D0 + G = 2* DSQRT(ALPHAS*PI) + CALL UPDATE_AS_PARAM() + IF (NHEL.NE.0) THEN + CALL ML5_0_SMATRIXHEL(P, NHEL, FLAV_IDX, ANS) + ELSE + CALL ML5_0_SMATRIX(P, FLAV_IDX, ANS) + ENDIF + RETURN + END + + SUBROUTINE ML5_0_INITIALISEMODEL(PATH) +C ROUTINE FOR F2PY to read the benchmark point. + IMPLICIT NONE + CHARACTER*512 PATH +CF2PY INTENT(IN) :: PATH + CALL SETPARA(PATH) !first call to setup the paramaters + RETURN + END + + LOGICAL FUNCTION ML5_0_IS_BORN_HEL_SELECTED(HELID) + IMPLICIT NONE +C +C CONSTANTS +C + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INTEGER NCOMB + PARAMETER (NCOMB=16) +C +C ARGUMENTS +C + INTEGER HELID +C +C LOCALS +C + INTEGER I,J + LOGICAL FOUNDIT +C +C GLOBALS +C + INTEGER HELC(NEXTERNAL,NCOMB) + COMMON/ML5_0_PROCESS_NHEL/HELC + + INTEGER POLARIZATIONS(0:NEXTERNAL,0:5) + COMMON/ML5_0_BORN_BEAM_POL/POLARIZATIONS +C ---------- +C BEGIN CODE +C ---------- + + ML5_0_IS_BORN_HEL_SELECTED = .TRUE. + IF (POLARIZATIONS(0,0).EQ.-1) THEN + RETURN + ENDIF + + DO I=1,NEXTERNAL + IF (POLARIZATIONS(I,0).EQ.-1) THEN + CYCLE + ENDIF + FOUNDIT = .FALSE. + DO J=1,POLARIZATIONS(I,0) + IF (HELC(I,HELID).EQ.POLARIZATIONS(I,J)) THEN + FOUNDIT = .TRUE. + EXIT + ENDIF + ENDDO + IF(.NOT.FOUNDIT) THEN + ML5_0_IS_BORN_HEL_SELECTED = .FALSE. + RETURN + ENDIF + ENDDO + + RETURN + END + + + INTEGER FUNCTION ML5_0_BROKEN_SYM(FLAV) + INCLUDE 'nexternal.inc' + INTEGER FLAV(NEXTERNAL) + INTEGER I,J,K,ICOMP + INTEGER N_TOT, OLD_FACTOR, TOTAL_FACTOR + INTEGER NCOMP, NENTRIES + PARAMETER (NCOMP=1) + PARAMETER (NENTRIES=2) + INTEGER COMP_BEG(NCOMP), COMP_END(NCOMP), COMP_OLD(NCOMP) + INTEGER PID_LIST(NENTRIES), PID_WORK(NENTRIES) + INTEGER BLOCK_START(NENTRIES), BLOCK_LEN(NENTRIES) + LOGICAL SAME_BLOCK + DATA COMP_BEG /1/ + DATA COMP_END /2/ + DATA COMP_OLD /1/ + DATA PID_LIST /6,-6/ + DATA BLOCK_START /3,4/ + DATA BLOCK_LEN /1,1/ + + PID_WORK = PID_LIST + TOTAL_FACTOR = 1 + DO ICOMP=1,NCOMP + OLD_FACTOR = COMP_OLD(ICOMP) + IF (COMP_OLD(ICOMP).GT.1) THEN + DO I=COMP_BEG(ICOMP),COMP_END(ICOMP) + IF (PID_WORK(I).EQ.0) CYCLE + N_TOT = 1 + DO J=I+1,COMP_END(ICOMP) + IF (PID_WORK(I).EQ.PID_WORK(J)) THEN + SAME_BLOCK = .TRUE. + IF (BLOCK_LEN(I).NE.BLOCK_LEN(J)) SAME_BLOCK = .FALSE. + DO K=1,BLOCK_LEN(I) + IF (FLAV(BLOCK_START(I)+K-1).NE.FLAV(BLOCK_START(J) + $ +K-1)) THEN + SAME_BLOCK = .FALSE. + ENDIF + ENDDO + IF (SAME_BLOCK) THEN + PID_WORK(J) = 0 + N_TOT = N_TOT + 1 + OLD_FACTOR = OLD_FACTOR/N_TOT + ENDIF + ENDIF + ENDDO + ENDDO + ENDIF + TOTAL_FACTOR = TOTAL_FACTOR*OLD_FACTOR + ENDDO + ML5_0_BROKEN_SYM = TOTAL_FACTOR + RETURN + END + + + + INTEGER FUNCTION ML5_0_GET_FLAVOR_INDEX(FLAVOR) +C Resolve an external FLAVOR(NEXTERNAL) group-position vector to +C its +C 1-based index in the allowed-flavor table (the same ordering +C used by +C compute_flavor_masks / the FLAV_TABLE mask columns). A resolved +C flavor +C returns an index in [1,NFLAV]; a flavor that is NOT in the table +C (i.e. +C not a physical/allowed combination, so its matrix element is +C zero) +C returns 0. Callers MUST treat the 0 sentinel as "not a valid +C flavor" +C and short-circuit to a zero result before indexing the 1..NFLAV +C GOODHEL/NTRY arrays or FLAV_TABLE (there is no reserved 0 slot). +C Computed once per phase-space point and then threaded down to +C MATRIX/GET_AMP and the good-helicity filter. + INCLUDE 'nexternal.inc' + INTEGER NFLAV + PARAMETER (NFLAV=1) + INTEGER FLAVOR(NEXTERNAL) +CF2PY INTENT(IN) :: FLAVOR(NEXTERNAL) +CF2PY INTENT(OUT) :: ML5_0_GET_FLAVOR_INDEX + INTEGER FI_I, FI_J + LOGICAL FI_MATCH + INTEGER FI_TABLE(NEXTERNAL, NFLAV) + DATA FI_TABLE /1, 1, 1, 1/ +C 0 sentinel for an unresolved (not-in-table) flavor (see above). + ML5_0_GET_FLAVOR_INDEX = 0 + DO FI_I = 1, NFLAV + FI_MATCH = .TRUE. + DO FI_J = 1, NEXTERNAL + IF (FLAVOR(FI_J) .NE. FI_TABLE(FI_J, FI_I)) THEN + FI_MATCH = .FALSE. + EXIT + ENDIF + ENDDO + IF (FI_MATCH) THEN + ML5_0_GET_FLAVOR_INDEX = FI_I + RETURN + ENDIF + ENDDO + RETURN + END + + + + SUBROUTINE ML5_0_GET_FLAVOR(FLAV_IDX, FLAVOR) +C Reverse of GET_FLAVOR_INDEX: fill FLAVOR(NEXTERNAL) with the +C per-leg +C group-position vector of the FLAV_IDX-th allowed flavor (same +C table / +C ordering). FLAV_IDX is expected in [1,NFLAV] (GET_FLAVOR_INDEX +C never +C returns 0); the bounds guard below is purely defensive and maps +C any +C out-of-range value to the first flavor. Used by the outer entry +C points +C (SMATRIX, ...) which receive FLAV_IDX but still need the FLAVOR +C array +C (e.g. for BROKEN_SYM). + INCLUDE 'nexternal.inc' + INTEGER NFLAV + PARAMETER (NFLAV=1) + INTEGER FLAV_IDX + INTEGER FLAVOR(NEXTERNAL) +CF2PY INTENT(IN) :: FLAV_IDX +CF2PY INTENT(OUT) :: FLAVOR(NEXTERNAL) + INTEGER FA_I, FA_USE + INTEGER FA_TABLE(NEXTERNAL, NFLAV) + DATA FA_TABLE /1, 1, 1, 1/ + FA_USE = FLAV_IDX + IF (FA_USE .LT. 1 .OR. FA_USE .GT. NFLAV) FA_USE = 1 + DO FA_I = 1, NEXTERNAL + FLAVOR(FA_I) = FA_TABLE(FA_I, FA_USE) + ENDDO + RETURN + END + + diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/born_matrix.ps b/UNITTEST_proc/SubProcesses/P0_gg_ttx/born_matrix.ps new file mode 100644 index 0000000000000000000000000000000000000000..a36c96a56f059bdb3e2cd4faeb4b57e5c652c2aa GIT binary patch literal 13824 zcmeHOS&!q!5q|Gq(Ro;47syKDrNe*$uRT^0BX)e`L=YGpi6aq~M46;^B@8CNJzrII zH=7i>J2Tll81Z07BeJXOKDxSlU;O6VA6~y%7q{8#a5PabUVL7h4(t4|`MfxPqF;v- z{*9A~*7N~@n__j^XNP)O9O~*5{rhb9HmmbhilJ}QO@>!G0NiiBPS?LH)8kgXP%rc{ zyBzlELEq%*rcC#hUYF^+gTB3J3zqzte*MK~-~91U4F8u3Ea>Hz|M=$XH{a-+@8A3l zNZ#mUSA zyedHcP3_D&{ z`R1VSCwi0V``|&}zs5&?m+h)dAb{;Qt@29U7=hc>p%%Y ze?v`H!zU^1w&H0-P)5l@#OqoVEuSUZHsnv??Eua2SV`f=49omLZ)%PC0B|t)#=Maa zD6$c7koDmP40uh1vFeZwY=FsCSWFUcUm#`+Jwc>8-&G((G684asLCjPmmg@tgT5hxiBE5GG@ONj0L{WyW4A8a}T? zS~4z8@hxk7optG3<$^iT4ukR>P$usH305WPo__r~WohWF#1l?O2`k3q-if!g!>iuH zr93c_a|yOdptMG^6hZ1Oxnu}X84`ExfI$}%y+c$18h*MB=z$U$tVvJ&K}m*?8;>9b zP88gYCJ6){+$4S#axSuyR8E1vuD9M48k6i~*zE}x3KIz!g9-B~bUVS~*dQpH6U-$m zB7c&}mSrirEe9isb!H-oM0-ypu_cWv9>{$WZ;#-BI8jK1l<~w5Ot3MF2A>~nsxR0m zy03x_t}d!&dl{3kevSOD%z!wBEAc@7D20UdPY6&tH8LwQ3?5i-^;WHl%6lQ1?J=>P zmSyoy-P?@8c^!3uxuPtNDuC~*GznsfF|jm33Y2>T_+eO*gSiGqgW*zhgwk7!|1RI{ zn#6P57Ikq@_xDYx+dST*G3Z>X7}X|JWJCjN$JeS+B~&P$CaIsm#MU+gxHN(IC7FP) z2bWlgtDU0c?>{=?$fr(Sd7Z&;k6& z-4t;oCZ#8yFc9Tja&1Nh?*a_oeeAvdJcOO|4_S$RA%U#mu|UBJs!3~`-HEaquRHYP za+|FNly!aXn&lmbui>kk+bC-f>dWRP%QpSB4o81E$#eSas-j7MK1&^_0abB(k*j{! z>tpFb^<+raBogFvRXJg`pb5Tq(+{Y!Z;tBY`>Cq*S$di(`&e?7$G2{eDzP+SUD^~P z3gv9#g3zXpCJ3o4_FM4U>f)2{aYUb0R~Kke{KN>oCT-%HV&G{GM`7!7>|Ivwv133h z$>+5;hwR-kr3GMrKdPj`m!%Hk&MYe#8U)P(%=BiDuMth!saEMOMX*>t41pHnuC(xn zG1>@kyJ1jvxDdGZApN$^(rns0)zjW_4wE*cr@iB5%I0+I&r&pGPSf5gX$hP5j$NQ{ z4l1GFm(gAg=K_dg8#4P2)0MY-!flra=A)tZ&a}bYazJSo+dzA#Tzg0U{=W8(@KR;r z_KtQF06*B?scuh5EeMAcUvFI3EbStq1j5y)d6K0e;&{(aua0z zk+AX-z%;7xvW;+w5h>pmiyJXriY!c4Hob77Aht~G8@#4G^8hb?x{m#;tD^Ha?)$5& z4!f#LaksnT*6us5y&PwAmDvrQa3=|TdQ+uuGljsxMkOXtDyp&?8`c-iee0&grgBkY zgg4L}p>4j|@W$<6?xZc#CUfQhOxv)NseTJ4$M?D4`EWFJFGfcyIxf$WZ8 ze_^~%tL^UK61V!Nc_DxPg$4pb(nF^*$-e4UWwJ^z(nA&&A6?vY>*g<0erGV3VV$|$ z8@+6|ajdD2mB*yiit^yI+0zOxn5CK}%YUkf#B{^BUvLGqv!B{uaN!M9S-g!<>$b8? zmR(Ql-bC(k1y^0~rw$fe*^D=3s;Qm*`>Be8d@kcD;*={#P1V(&FGgCdWT>(T#t775~b{zp3?|2uJ6zEpUMJ?D!s75954^54?Ee z)?3N7J*JiXxNTsMF@j6VBWIPPkmm41yue?H=d@=_TXwwu13_{>69w!BXm)%E#0Eo@ zd?<){u23kd27Huqodh_h2&;=FB}t%J&agT^ZWf^Ur+*NQMUjGl7bLI5@~;c-=4gc1 z#(_N=`Cl%$pK~fP?9}FT#2yh*g6KFct?9}0D2S+0MzS!C`HJ6j`^M{dlSOC|?%bRc zhI4aX^cXkqEdQy=Y?l8*X?XchiPJ6rUEvs7{$IrlE)DQ0!E@IaAILvat!nRpKx&o$ zMp|iE5n+c;!i&|$Rn&hY?Y3z;?EqVfdrALIFIEAi+U$e2uzJY_2?!0MInWV?;M|ga z%(9S=FXWhqE$#Ll0Eqm^lg>L%ttM?SqhVgcewdNi(dLG%UEDN-B!n5w0gPPrsX!{YYey%f}=YU(IYmR>Ir^n|D{d3L4JG; zaza8GoOJXQ^jSs+#l9*u^re@iO^eeOb$ta!)Cklv3uM4X2<#j?Qf-TOVv|O_{H}}B zPG}UTjJ;m|{S`zzWtxU~x9koEtFr@tr;pp);;h{12C+ff=Dc;y6V{usG9NCQvk_-^ z@ej&_EqbbtUdzOE1&FF9E&_yUP!2 z4m&JH)Htv0=pX8Im#;d*)kTkgxa@C>U3)-{-(_oDpi<*|J-(n7H=^F$p2_wa`} z6tj~aHpmt-l^Agyj^V|SHEyK@9F;i2(-w=0I%cG+%0X`z^I}k(!e-suQ&gC zdgxDo;&9uCz$utPxfgS41=3g|h!sS0ZtzO3WF)saIPsy;Qsa(b9RMI`3Dy~=`7Oyh z<4W?juq=E^(6@Hrq`3W;#ZH7JLQkh%SxJ1oAf&FXV`?s_0E0J;rv1Z5qJ0}C1Aa+Uod zv<{WK0KTU!a@-KUy8mrZ%o3dd32se~rmY`6jgk>9(B(v0E9|d?qp0T(n?MA`283olDRy&WP8cf<$V^EzX@1;t(9o5iL9V8b{=4~25kMy&M z1e!+k5x95Q8;QedG@4JMCQuA~)Tg-zX0=g)gpoU4?q+ZtlcJk?P7IavE0iq5MZf5Kz4zhJE({wQ# z#gk|@3n#NAisq4Su|BzGeYzNhlVCodV%BuJK$&u^I|lkVpF!p}B{wl@CI$g{sZOHU z_XxBG{2w4tO+C;>52$|m-4{2XhQHO{eR=cg!~x?!VE}CcVG$ql9Z}+mnjjd6?mTF@ zL+vnN8te#&gaV<5^#}n=q34tGqAgm)eFPeR(@`ue0Ea{0gqWb6k_)y-crwI^acQ_n zgQ5{Z1gBu~k@*PbEF$>?QkG-FcS)m#SwN&5MB{p-g)Rk83$dtq3T5~duC*`_@;X|O zAqV{<^!y{9^?(leM~DoB9k>`dOuo&?Q#{om=!tGL?f8cut#ej?6tx_rQ4P{emw>04 zAXxMf@H8VCm{2&qH}2uHE#KpWT*VV1n6Y(Zn6BTr{yb4gyl4eUC_Kiqw)Gkh)1l}f zUbNh!iErqDaQc*d9f*><_^)(8D4Y(OdZ116K%(^}bjc&~oFkCr(FPrG4l00Dsj*a` K%fvgZH~s?}h0xsq literal 0 HcmV?d00001 diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/check_sa.f b/UNITTEST_proc/SubProcesses/P0_gg_ttx/check_sa.f new file mode 100644 index 0000000000..36955bbc9b --- /dev/null +++ b/UNITTEST_proc/SubProcesses/P0_gg_ttx/check_sa.f @@ -0,0 +1,746 @@ + PROGRAM DRIVER +C ***************************************************************** +C ******** +C THIS IS THE DRIVER FOR CHECKING THE STANDALONE MATRIX ELEMENT. +C IT USES A SIMPLE PHASE SPACE GENERATOR +C ***************************************************************** +C ******** + IMPLICIT NONE +C +C CONSTANTS +C + REAL*8 ZERO + PARAMETER (ZERO=0D0) + + LOGICAL READPS + PARAMETER (READPS = .FALSE.) + + INTEGER NPSPOINTS + PARAMETER (NPSPOINTS = 4) + +C integer nexternal and number particles (incoming+outgoing) in +C the me + INTEGER NEXTERNAL, NINCOMING + PARAMETER (NEXTERNAL=4,NINCOMING=2) + + CHARACTER(512) MADLOOPRESOURCEPATH + +C +C INCLUDE FILES +C +C the include file with the values of the parameters and masses +C + INCLUDE 'coupl.inc' +C particle masses + REAL*8 PMASS(NEXTERNAL) +C integer n_max_cg + INCLUDE 'ngraphs.inc' + INCLUDE 'nsqso_born.inc' + INCLUDE 'nsquaredSO.inc' + +C +C LOCAL +C + INTEGER I,J,K +C four momenta. Energy is the zeroth component. + REAL*8 P(0:3,NEXTERNAL) + INTEGER MATELEM_ARRAY_DIM + REAL*8 , ALLOCATABLE :: MATELEM(:,:) + REAL*8 SQRTS,AO2PI,TOTMASS +C sqrt(s)= center of mass energy + REAL*8 PIN(0:3), POUT(0:3) + CHARACTER*120 BUFF(NEXTERNAL) + INTEGER RETURNCODE, UNITS, TENS, HUNDREDS + INTEGER NSQUAREDSO_LOOP + REAL*8 , ALLOCATABLE :: PREC_FOUND(:) + +C +C GLOBAL VARIABLES +C +C This is from ML code for the list of split orders selected by +C the process definition +C + INTEGER NLOOPCHOSEN + CHARACTER*20 CHOSEN_LOOP_SO_INDICES(NSQUAREDSO) + LOGICAL CHOSEN_LOOP_SO_CONFIGS(NSQUAREDSO) + COMMON/ML5_0_CHOSEN_LOOP_SQSO/CHOSEN_LOOP_SO_CONFIGS + INTEGER NBORNCHOSEN + CHARACTER*20 CHOSEN_BORN_SO_INDICES(NSQSO_BORN) + LOGICAL CHOSEN_BORN_SO_CONFIGS(NSQSO_BORN) + COMMON/ML5_0_CHOSEN_BORN_SQSO/CHOSEN_BORN_SO_CONFIGS + +C +C SAVED VARIABLES +C + LOGICAL INIT + DATA INIT/.TRUE./ + COMMON/INITCHECKSA/INIT +C +C EXTERNAL +C + REAL*8 DOT + EXTERNAL DOT + +C +C BEGIN CODE +C +C + + IF (INIT) THEN + INIT=.FALSE. + CALL ML5_0_GET_ANSWER_DIMENSION(MATELEM_ARRAY_DIM) + ALLOCATE(MATELEM(0:3,0:MATELEM_ARRAY_DIM)) + CALL ML5_0_GET_NSQSO_LOOP(NSQUAREDSO_LOOP) + ALLOCATE(PREC_FOUND(0:NSQUAREDSO_LOOP)) + +C INITIALIZATION CALLS +C +C Call to initialize the values of the couplings, masses and +C widths +C used in the evaluation of the matrix element. The primary +C parameters of the +C models are read from Cards/param_card.dat. The secondary +C parameters are calculated +C in Source/MODEL/couplings.f. The values are stored in common +C blocks that are listed +C in coupl.inc . +C first call to setup the paramaters + CALL SETPARA('param_card.dat') +C set up masses + INCLUDE 'pmass.inc' + + ENDIF + + +C Start by initializing what is the squared split orders indices +C chosen + NLOOPCHOSEN=0 + DO I=1,NSQUAREDSO + IF (CHOSEN_LOOP_SO_CONFIGS(I)) THEN + NLOOPCHOSEN=NLOOPCHOSEN+1 + WRITE(CHOSEN_LOOP_SO_INDICES(NLOOPCHOSEN),'(I3,A2)') I,'L)' + ENDIF + ENDDO + NBORNCHOSEN=0 + DO I=1,NSQSO_BORN + IF (CHOSEN_BORN_SO_CONFIGS(I)) THEN + NBORNCHOSEN=NBORNCHOSEN+1 + WRITE(CHOSEN_BORN_SO_INDICES(NBORNCHOSEN),'(I3,A2)') I,'B)' + ENDIF + ENDDO + + AO2PI=G**2/(8.D0*(3.14159265358979323846D0**2)) + + WRITE(*,*) 'AO2PI=',AO2PI +C Now use a simple multipurpose PS generator (RAMBO) just to get a +C RANDOM set of four momenta of given masses pmass(i) to be used +C to evaluate +C the madgraph matrix-element. +C Alternatevely, here the user can call or set the four momenta at +C his will, see below. +C + IF(NINCOMING.EQ.1) THEN + SQRTS=PMASS(1) + ELSE + TOTMASS = 0.0D0 + DO I=1,NEXTERNAL + TOTMASS = TOTMASS + PMASS(I) + ENDDO +C CMS energy in GEV + SQRTS=MAX(1000D0,2.0D0*TOTMASS) + ENDIF + + CALL PRINTOUT() + + + + DO K=1,NPSPOINTS + + IF(READPS) THEN + OPEN(967, FILE='PS.input', ERR=976, STATUS='OLD', + $ ACTION='READ') + DO I=1,NEXTERNAL + READ(967,*,END=978) P(0,I),P(1,I),P(2,I),P(3,I) + ENDDO + GOTO 978 + 976 CONTINUE + STOP 'Could not read the PS.input phase-space point.' + 978 CONTINUE + CLOSE(967) + ELSE + IF ((NINCOMING.EQ.2).AND.((NEXTERNAL - NINCOMING .EQ.1))) + $ THEN + IF (PMASS(3).EQ.0.0D0) THEN + STOP 'Cannot generate 2>1 kin. config. with m3=0.0d0' + ELSE +C deal with the case of only one particle in the final +C state + P(0,1) = PMASS(3)/2D0 + P(1,1) = 0D0 + P(2,1) = 0D0 + P(3,1) = PMASS(3)/2D0 + IF (PMASS(1).GT.0D0) THEN + P(3,1) = DSQRT(PMASS(3)**2/4D0 - PMASS(1)**2) + ENDIF + P(0,2) = PMASS(3)/2D0 + P(1,2) = 0D0 + P(2,2) = 0D0 + P(3,2) = -PMASS(3)/2D0 + IF (PMASS(2) > 0D0) THEN + P(3,2) = -DSQRT(PMASS(3)**2/4D0 - PMASS(1)**2) + ENDIF + P(0,3) = PMASS(3) + P(1,3) = 0D0 + P(2,3) = 0D0 + P(3,3) = 0D0 + ENDIF + ELSE + CALL GET_MOMENTA(SQRTS,PMASS,P) + ENDIF + ENDIF + + DO I=0,3 + PIN(I)=0.0D0 + DO J=1,NINCOMING + PIN(I)=PIN(I)+P(I,J) + ENDDO + ENDDO + +C In standalone mode, always use sqrt_s as the renormalization +C scale. + SQRTS=DSQRT(DABS(DOT(PIN(0),PIN(0)))) + MU_R=SQRTS + +C Update the couplings with the new MU_R + CALL UPDATE_AS_PARAM() + +C Optionally the user can set where to find the +C MadLoop5_resources folder. +C Otherwise it will look for it automatically and find it if it +C has not +C been moved +C MadLoopResourcePath = '' +C CALL SETMADLOOPPATH(MadLoopResourcePath) +C To force the stabiliy check to also be performed in the +C initialization phase +C CALL ML5_0_FORCE_STABILITY_CHECK(.TRUE.) +C To chose a particular tartget split order, SOTARGET is an +C integer labeling +C the possible squared order couplings contributions (only in +C optimized mode) +C CALL ML5_0_SET_COUPLINGORDERS_TARGET(SOTARGET) + + +C +C Now we can call the matrix element +C + CALL ML5_0_SLOOPMATRIX_THRES(P,MATELEM,-1.0D0,PREC_FOUND + $ ,RETURNCODE) + +C +C write the information on the four momenta +C + IF (K.EQ.NPSPOINTS) THEN + WRITE (*,*) + WRITE (*,*) ' Phase space point:' + WRITE (*,*) + WRITE (*,*) '---------------------------------' + WRITE (*,*) 'n E px py pz m' + DO I=1,NEXTERNAL + WRITE (*,'(i2,1x,5e15.7)') I, P(0,I),P(1,I),P(2,I),P(3,I) + $ ,DSQRT(DABS(DOT(P(0,I),P(0,I)))) + ENDDO + WRITE (*,*) '---------------------------------' + WRITE (*,*) 'Detailed result for each coupling orders' + $ //' combination.' + + + UNITS=MOD(RETURNCODE,10) + TENS=(MOD(RETURNCODE,100)-UNITS)/10 + HUNDREDS=(RETURNCODE-TENS*10-UNITS)/100 + IF (HUNDREDS.EQ.1) THEN + IF (TENS.EQ.3.OR.TENS.EQ.4) THEN + WRITE(*,*) 'Unknown numerical stability because MadLoop' + $ //' is in the initialization stage.' + ELSE + WRITE(*,*) 'Unknown numerical stability, check CTModeRun' + $ //' value in MadLoopParams.dat.' + ENDIF + ELSEIF (HUNDREDS.EQ.2) THEN + WRITE(*,*) 'Stable kinematic configuration (SPS).' + ELSEIF (HUNDREDS.EQ.3) THEN + WRITE(*,*) 'Unstable kinematic configuration (UPS).' + WRITE(*,*) 'Quadruple precision rescue successful.' + ELSEIF (HUNDREDS.EQ.4) THEN + WRITE(*,*) 'Exceptional kinematic configuration (EPS).' + WRITE(*,*) 'Both double an quadruple precision' + $ //' computations, are unstable.' + ENDIF + IF (TENS.EQ.2.OR.TENS.EQ.4) THEN + WRITE(*,*) 'Quadruple precision computation used.' + ENDIF + IF (HUNDREDS.NE.1) THEN + IF (PREC_FOUND(0).GT.0.0D0) THEN + WRITE(*,'(1x,a23,1x,1e10.2)') 'Relative accuracy =' + $ ,PREC_FOUND(0) + ELSEIF (PREC_FOUND(0).EQ.0.0D0) THEN + WRITE(*,'(1x,a23,1x,1e10.2,1x,a30)') 'Relative accuracy ' + $ //' =',PREC_FOUND(0),'(i.e. beyond double precision)' + ELSE + WRITE(*,*) 'Estimated accuracy could not be computed for' + $ //' an unknown reason.' + ENDIF + ENDIF + WRITE (*,'(1x,a23,3x,i3)') 'MadLoop return code =' + $ ,RETURNCODE + WRITE (*,*) '---------------------------------' + IF (NBORNCHOSEN.EQ.0) THEN + WRITE (*,*) 'No Born contribution satisfied the squared' + $ //' order constraints.' + ELSE IF (NBORNCHOSEN.NE.NSQSO_BORN) THEN + WRITE (*,*) 'Selected squared coupling orders combination' + $ //' for the Born summed result below:' + WRITE (*,*) (CHOSEN_BORN_SO_INDICES(I),I=1,NBORNCHOSEN) + ENDIF + IF (NLOOPCHOSEN.NE.NSQUAREDSO) THEN + WRITE (*,*) 'Selected squared coupling orders combination' + $ //' for the loop summed result below:' + WRITE (*,*) (CHOSEN_LOOP_SO_INDICES(I),I=1,NLOOPCHOSEN) + ENDIF + WRITE (*,*) '---------------------------------' + WRITE (*,*) 'Matrix element born = ', MATELEM(0,0), + $ ' GeV^',-(2*NEXTERNAL-8) + WRITE (*,*) 'Matrix element finite = ', MATELEM(1,0), + $ ' GeV^',-(2*NEXTERNAL-8) + WRITE (*,*) 'Matrix element 1eps = ', MATELEM(2,0), + $ ' GeV^',-(2*NEXTERNAL-8) + WRITE (*,*) 'Matrix element 2eps = ', MATELEM(3,0), + $ ' GeV^',-(2*NEXTERNAL-8) + WRITE (*,*) '---------------------------------' + IF (MATELEM(0,0).NE.0.0D0) THEN + WRITE (*,*) 'finite / (born*ao2pi) = ', MATELEM(1,0) + $ /MATELEM(0,0)/AO2PI + WRITE (*,*) '1eps / (born*ao2pi) = ', MATELEM(2,0) + $ /MATELEM(0,0)/AO2PI + WRITE (*,*) '2eps / (born*ao2pi) = ', MATELEM(3,0) + $ /MATELEM(0,0)/AO2PI + ELSE + WRITE (*,*) 'finite / ao2pi = ', MATELEM(1,0)/AO2PI + WRITE (*,*) '1eps / ao2pi = ', MATELEM(2,0)/AO2PI + WRITE (*,*) '2eps / ao2pi = ', MATELEM(3,0)/AO2PI + ENDIF + WRITE (*,*) '---------------------------------' + + OPEN(69, FILE='result.dat', ERR=976, ACTION='WRITE') + DO I=1,NEXTERNAL + WRITE (69,'(a2,1x,5ES30.15E3)') 'PS',P(0,I),P(1,I),P(2,I) + $ ,P(3,I) + ENDDO + WRITE (69,'(a3,1x,i3)') 'EXP',-(2*NEXTERNAL-8) + WRITE (69,'(a4,1x,1ES30.15E3)') 'BORN',MATELEM(0,0) + IF (MATELEM(0,0).NE.0.0D0) THEN + WRITE (69,'(a3,1x,1ES30.15E3)') 'FIN',MATELEM(1,0) + $ /MATELEM(0,0)/AO2PI + WRITE (69,'(a4,1x,1ES30.15E3)') '1EPS',MATELEM(2,0) + $ /MATELEM(0,0)/AO2PI + WRITE (69,'(a4,1x,1ES30.15E3)') '2EPS',MATELEM(3,0) + $ /MATELEM(0,0)/AO2PI + ELSE + WRITE (69,'(a3,1x,1ES30.15E3)') 'FIN',MATELEM(1,0)/AO2PI + WRITE (69,'(a4,1x,1ES30.15E3)') '1EPS',MATELEM(2,0)/AO2PI + WRITE (69,'(a4,1x,1ES30.15E3)') '2EPS',MATELEM(3,0)/AO2PI + ENDIF + WRITE (69,'(a6,1x,1ES30.15E3)') 'ASO2PI',AO2PI + WRITE (69,*) 'Export_Format Default' + WRITE (69,'(a7,1x,i3)') 'RETCODE',RETURNCODE + WRITE (69,'(a3,1x,1e10.4)') 'ACC',PREC_FOUND(0) + WRITE (69,*) 'Born_kept',(CHOSEN_BORN_SO_CONFIGS(I),I=1 + $ ,NSQSO_BORN) + WRITE (69,*) 'Loop_kept',(CHOSEN_LOOP_SO_CONFIGS(I),I=1 + $ ,NSQUAREDSO) + + + CLOSE(69) + ELSE + WRITE (*,*) 'PS Point #',K,' done.' + ENDIF + ENDDO + +C C +C C Copy down here (or read in) the four momenta as a string. +C C +C C +C buff(1)=" 1 0.5630480E+04 0.0000000E+00 0.0000000E+00 +C 0.5630480E+04" +C buff(2)=" 2 0.5630480E+04 0.0000000E+00 0.0000000E+00 +C -0.5630480E+04" +C buff(3)=" 3 0.5466073E+04 0.4443190E+03 0.2446331E+04 +C -0.4864732E+04" +C buff(4)=" 4 0.8785819E+03 -0.2533886E+03 0.2741971E+03 +C 0.7759741E+03" +C buff(5)=" 5 0.4916306E+04 -0.1909305E+03 -0.2720528E+04 +C 0.4088757E+04" +C C +C C Here the k,E,px,py,pz are read from the string into the +C momenta array. +C C k=1,2 : incoming +C C k=3,nexternal : outgoing +C C +C do i=1,nexternal +C read (buff(i),*) k, P(0,i),P(1,i),P(2,i),P(3,i) +C enddo +C +C C print the momenta out +C +C do i=1,nexternal +C write (*,'(i2,1x,5e15.7)') i, P(0,i),P(1,i),P(2,i),P(3,i), +C &dsqrt(dabs(DOT(p(0,i),p(0,i)))) +C enddo +C +C CALL SLOOPMATRIX(P,MATELEM) +C +C write (*,*) "-------------------------------------------------" +C write (*,*) "Matrix element = ", MATELEM(1), " +C GeV^",-(2*nexternal-8) +C write (*,*) "-------------------------------------------------" + + DEALLOCATE(MATELEM) + DEALLOCATE(PREC_FOUND) + + END + + + + + DOUBLE PRECISION FUNCTION DOT(P1,P2) +C ************************************************************* +C 4-Vector Dot product +C ************************************************************* + IMPLICIT NONE + DOUBLE PRECISION P1(0:3),P2(0:3) + DOT=P1(0)*P2(0)-P1(1)*P2(1)-P1(2)*P2(2)-P1(3)*P2(3) + END + + + SUBROUTINE GET_MOMENTA(ENERGY,PMASS,P) +C auxiliary function to change convention between madgraph and +C rambo +C four momenta. + IMPLICIT NONE + INTEGER NEXTERNAL, NINCOMING + PARAMETER (NEXTERNAL=4,NINCOMING=2) +C ARGUMENTS + REAL*8 ENERGY,PMASS(NEXTERNAL),P(0:3,NEXTERNAL),PRAMBO(4,10),WGT +C LOCAL + INTEGER I + REAL*8 ETOT2,MOM,M1,M2,E1,E2 + + ETOT2=ENERGY**2 + M1=PMASS(1) + M2=PMASS(2) + MOM=(ETOT2**2 - 2*ETOT2*M1**2 + M1**4 - 2*ETOT2*M2**2 - 2*M1**2 + $ *M2**2 + M2**4)/(4.*ETOT2) + MOM=DSQRT(MOM) + E1=DSQRT(MOM**2+M1**2) + E2=DSQRT(MOM**2+M2**2) +C write (*,*) e1+e2,mom + + IF(NINCOMING.EQ.2) THEN + + P(0,1)=E1 + P(1,1)=0D0 + P(2,1)=0D0 + P(3,1)=MOM + + P(0,2)=E2 + P(1,2)=0D0 + P(2,2)=0D0 + P(3,2)=-MOM + + CALL RAMBO(NEXTERNAL-2,ENERGY,PMASS(NINCOMING+1),PRAMBO,WGT) + DO I=3, NEXTERNAL + P(0,I)=PRAMBO(4,I-2) + P(1,I)=PRAMBO(1,I-2) + P(2,I)=PRAMBO(2,I-2) + P(3,I)=PRAMBO(3,I-2) + ENDDO + + ELSEIF(NINCOMING.EQ.1) THEN + + P(0,1)=ENERGY + P(1,1)=0D0 + P(2,1)=0D0 + P(3,1)=0D0 + + CALL RAMBO(NEXTERNAL-1,ENERGY,PMASS(2),PRAMBO,WGT) + DO I=2, NEXTERNAL + P(0,I)=PRAMBO(4,I-1) + P(1,I)=PRAMBO(1,I-1) + P(2,I)=PRAMBO(2,I-1) + P(3,I)=PRAMBO(3,I-1) + ENDDO + ENDIF + + RETURN + END + + + SUBROUTINE RAMBO(N,ET,XM,P,WT) +C ***************************************************************** +C ***** +C RAMBO * +C RA(NDOM) M(OMENTA) B(EAUTIFULLY) O(RGANIZED) +C * +C * +C A DEMOCRATIC MULTI-PARTICLE PHASE SPACE GENERATOR +C * +C AUTHORS: S.D. ELLIS, R. KLEISS, W.J. STIRLING +C * +C THIS IS VERSION 1.0 - WRITTEN BY R. KLEISS +C * +C -- ADJUSTED BY HANS KUIJF, WEIGHTS ARE LOGARITHMIC (20-08-90) +C * +C * +C N = NUMBER OF PARTICLES +C * +C ET = TOTAL CENTRE-OF-MASS ENERGY +C * +C XM = PARTICLE MASSES ( DIM=NEXTERNAL-nincoming ) +C * +C P = PARTICLE MOMENTA ( DIM=(4,NEXTERNAL-nincoming) ) +C * +C WT = WEIGHT OF THE EVENT +C * +C ***************************************************************** +C ***** + IMPLICIT REAL*8(A-H,O-Z) + INTEGER NEXTERNAL, NINCOMING + PARAMETER (NEXTERNAL=4,NINCOMING=2) + DIMENSION XM(NEXTERNAL-NINCOMING),P(4,NEXTERNAL-NINCOMING) + DIMENSION Q(4,NEXTERNAL-NINCOMING),Z(NEXTERNAL-NINCOMING),R(4) + $ ,B(3),P2(NEXTERNAL-NINCOMING),XM2(NEXTERNAL-NINCOMING) + $ ,E(NEXTERNAL-NINCOMING),V(NEXTERNAL-NINCOMING),IWARN(5) + SAVE ACC,ITMAX,IBEGIN,IWARN + DATA ACC/1.D-14/,ITMAX/6/,IBEGIN/0/,IWARN/5*0/ +C +C INITIALIZATION STEP: FACTORIALS FOR THE PHASE SPACE WEIGHT + IF(IBEGIN.NE.0) GOTO 103 + IBEGIN=1 + TWOPI=8.*DATAN(1.D0) + PO2LOG=LOG(TWOPI/4.) + Z(2)=PO2LOG + DO 101 K=3,(NEXTERNAL-NINCOMING) + 101 Z(K)=Z(K-1)+PO2LOG-2.*LOG(DFLOAT(K-2)) + DO 102 K=3,(NEXTERNAL-NINCOMING) + 102 Z(K)=(Z(K)-LOG(DFLOAT(K-1))) +C +C CHECK ON THE NUMBER OF PARTICLES + 103 IF(N.GT.1.AND.N.LT.101) GOTO 104 + PRINT 1001,N + STOP +C +C CHECK WHETHER TOTAL ENERGY IS SUFFICIENT; COUNT NONZERO MASSES + 104 XMT=0. + NM=0 + DO 105 I=1,N + IF(XM(I).NE.0.D0) NM=NM+1 + 105 XMT=XMT+ABS(XM(I)) + IF(XMT.LE.ET) GOTO 201 + PRINT 1002,XMT,ET + STOP +C +C THE PARAMETER VALUES ARE NOW ACCEPTED +C +C GENERATE N MASSLESS MOMENTA IN INFINITE PHASE SPACE + 201 DO 202 I=1,N + R1=RN(1) + C=2.*R1-1. + S=SQRT(1.-C*C) + F=TWOPI*RN(2) + R1=RN(3) + R2=RN(4) + Q(4,I)=-LOG(R1*R2) + Q(3,I)=Q(4,I)*C + Q(2,I)=Q(4,I)*S*COS(F) + 202 Q(1,I)=Q(4,I)*S*SIN(F) +C +C CALCULATE THE PARAMETERS OF THE CONFORMAL TRANSFORMATION + DO 203 I=1,4 + 203 R(I)=0. + DO 204 I=1,N + DO 204 K=1,4 + 204 R(K)=R(K)+Q(K,I) + RMAS=SQRT(R(4)**2-R(3)**2-R(2)**2-R(1)**2) + DO 205 K=1,3 + 205 B(K)=-R(K)/RMAS + G=R(4)/RMAS + A=1./(1.+G) + X=ET/RMAS +C +C TRANSFORM THE Q'S CONFORMALLY INTO THE P'S + DO 207 I=1,N + BQ=B(1)*Q(1,I)+B(2)*Q(2,I)+B(3)*Q(3,I) + DO 206 K=1,3 + 206 P(K,I)=X*(Q(K,I)+B(K)*(Q(4,I)+A*BQ)) + 207 P(4,I)=X*(G*Q(4,I)+BQ) +C +C CALCULATE WEIGHT AND POSSIBLE WARNINGS + WT=PO2LOG + IF(N.NE.2) WT=(2.*N-4.)*LOG(ET)+Z(N) + IF(WT.GE.-180.D0) GOTO 208 + IF(IWARN(1).LE.5) PRINT 1004,WT + IWARN(1)=IWARN(1)+1 + 208 IF(WT.LE. 174.D0) GOTO 209 + IF(IWARN(2).LE.5) PRINT 1005,WT + IWARN(2)=IWARN(2)+1 +C +C RETURN FOR WEIGHTED MASSLESS MOMENTA + 209 IF(NM.NE.0) GOTO 210 +C RETURN LOG OF WEIGHT + WT=WT + RETURN +C +C MASSIVE PARTICLES: RESCALE THE MOMENTA BY A FACTOR X + 210 XMAX=SQRT(1.-(XMT/ET)**2) + DO 301 I=1,N + XM2(I)=XM(I)**2 + 301 P2(I)=P(4,I)**2 + ITER=0 + X=XMAX + ACCU=ET*ACC + 302 F0=-ET + G0=0. + X2=X*X + DO 303 I=1,N + E(I)=SQRT(XM2(I)+X2*P2(I)) + F0=F0+E(I) + 303 G0=G0+P2(I)/E(I) + IF(ABS(F0).LE.ACCU) GOTO 305 + ITER=ITER+1 + IF(ITER.LE.ITMAX) GOTO 304 + PRINT 1006,ITMAX + GOTO 305 + 304 X=X-F0/(X*G0) + GOTO 302 + 305 DO 307 I=1,N + V(I)=X*P(4,I) + DO 306 K=1,3 + 306 P(K,I)=X*P(K,I) + 307 P(4,I)=E(I) +C +C CALCULATE THE MASS-EFFECT WEIGHT FACTOR + WT2=1. + WT3=0. + DO 308 I=1,N + WT2=WT2*V(I)/E(I) + 308 WT3=WT3+V(I)**2/E(I) + WTM=(2.*N-3.)*LOG(X)+LOG(WT2/WT3*ET) +C +C RETURN FOR WEIGHTED MASSIVE MOMENTA + WT=WT+WTM + IF(WT.GE.-180.D0) GOTO 309 + IF(IWARN(3).LE.5) PRINT 1004,WT + IWARN(3)=IWARN(3)+1 + 309 IF(WT.LE. 174.D0) GOTO 310 + IF(IWARN(4).LE.5) PRINT 1005,WT + IWARN(4)=IWARN(4)+1 +C RETURN LOG OF WEIGHT + 310 WT=WT + RETURN +C + 1001 FORMAT(' RAMBO FAILS: # OF PARTICLES =',I5,' IS NOT ALLOWED') + 1002 FORMAT(' RAMBO FAILS: TOTAL MASS =',D15.6,' IS NOT',' SMALLER' + $ //' THAN TOTAL ENERGY =',D15.6) + 1004 FORMAT(' RAMBO WARNS: WEIGHT = EXP(',F20.9,') MAY UNDERFLOW') + 1005 FORMAT(' RAMBO WARNS: WEIGHT = EXP(',F20.9,') MAY OVERFLOW') + 1006 FORMAT(' RAMBO WARNS:',I3,' ITERATIONS DID NOT GIVE THE', + $ ' DESIRED ACCURACY =',D15.6) + END + + FUNCTION RN(IDUMMY) + REAL*8 RN,RAN + SAVE INIT + DATA INIT /1/ + IF (INIT.EQ.1) THEN + INIT=0 + CALL RMARIN(1802,9373) + END IF +C + 10 CALL RANMAR(RAN) + IF (RAN.LT.1D-16) GOTO 10 + RN=RAN +C + END + + + + SUBROUTINE RANMAR(RVEC) +C ----------------- +C Universal random number generator proposed by Marsaglia and Zaman +C in report FSU-SCRI-87-50 +C In this version RVEC is a double precision variable. + IMPLICIT REAL*8(A-H,O-Z) + COMMON/ RASET1 / RANU(97),RANC,RANCD,RANCM + COMMON/ RASET2 / IRANMR,JRANMR + SAVE /RASET1/,/RASET2/ + UNI = RANU(IRANMR) - RANU(JRANMR) + IF(UNI .LT. 0D0) UNI = UNI + 1D0 + RANU(IRANMR) = UNI + IRANMR = IRANMR - 1 + JRANMR = JRANMR - 1 + IF(IRANMR .EQ. 0) IRANMR = 97 + IF(JRANMR .EQ. 0) JRANMR = 97 + RANC = RANC - RANCD + IF(RANC .LT. 0D0) RANC = RANC + RANCM + UNI = UNI - RANC + IF(UNI .LT. 0D0) UNI = UNI + 1D0 + RVEC = UNI + END + + SUBROUTINE RMARIN(IJ,KL) +C ----------------- +C Initializing routine for RANMAR, must be called before generating +C any pseudorandom numbers with RANMAR. The input values should be +C in +C the ranges 0<=ij<=31328 ; 0<=kl<=30081 + IMPLICIT REAL*8(A-H,O-Z) + COMMON/ RASET1 / RANU(97),RANC,RANCD,RANCM + COMMON/ RASET2 / IRANMR,JRANMR + SAVE /RASET1/,/RASET2/ +C This shows correspondence between the simplified input seeds IJ, +C KL +C and the original Marsaglia-Zaman seeds I,J,K,L. +C To get the standard values in the Marsaglia-Zaman paper +C (i=12,j=34 +C k=56,l=78) put ij=1802, kl=9373 + I = MOD( IJ/177 , 177 ) + 2 + J = MOD( IJ , 177 ) + 2 + K = MOD( KL/169 , 178 ) + 1 + L = MOD( KL , 169 ) + DO 300 II = 1 , 97 + S = 0D0 + T = .5D0 + DO 200 JJ = 1 , 24 + M = MOD( MOD(I*J,179)*K , 179 ) + I = J + J = K + K = M + L = MOD( 53*L+1 , 169 ) + IF(MOD(L*M,64) .GE. 32) S = S + T + T = .5D0*T + 200 CONTINUE + RANU(II) = S + 300 CONTINUE + RANC = 362436D0 / 16777216D0 + RANCD = 7654321D0 / 16777216D0 + RANCM = 16777213D0 / 16777216D0 + IRANMR = 97 + JRANMR = 33 + END + + + + + + + diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/coupl.inc b/UNITTEST_proc/SubProcesses/P0_gg_ttx/coupl.inc new file mode 120000 index 0000000000..daef53f7ac --- /dev/null +++ b/UNITTEST_proc/SubProcesses/P0_gg_ttx/coupl.inc @@ -0,0 +1 @@ +../coupl.inc \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/cts_mpc.h b/UNITTEST_proc/SubProcesses/P0_gg_ttx/cts_mpc.h new file mode 120000 index 0000000000..cfea8d8631 --- /dev/null +++ b/UNITTEST_proc/SubProcesses/P0_gg_ttx/cts_mpc.h @@ -0,0 +1 @@ +../cts_mpc.h \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/cts_mprec.h b/UNITTEST_proc/SubProcesses/P0_gg_ttx/cts_mprec.h new file mode 120000 index 0000000000..1d74785701 --- /dev/null +++ b/UNITTEST_proc/SubProcesses/P0_gg_ttx/cts_mprec.h @@ -0,0 +1 @@ +../cts_mprec.h \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/global_specs.inc b/UNITTEST_proc/SubProcesses/P0_gg_ttx/global_specs.inc new file mode 120000 index 0000000000..5bfc3e70cd --- /dev/null +++ b/UNITTEST_proc/SubProcesses/P0_gg_ttx/global_specs.inc @@ -0,0 +1 @@ +../global_specs.inc \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/improve_ps.f b/UNITTEST_proc/SubProcesses/P0_gg_ttx/improve_ps.f new file mode 100644 index 0000000000..9e4f86735e --- /dev/null +++ b/UNITTEST_proc/SubProcesses/P0_gg_ttx/improve_ps.f @@ -0,0 +1,1014 @@ + SUBROUTINE ML5_0_IMPROVE_PS_POINT_PRECISION(P) + IMPLICIT NONE +C +C CONSTANTS +C + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) +C +C ARGUMENTS +C + DOUBLE PRECISION P(0:3,NEXTERNAL) + REAL*16 QP_P(0:3,NEXTERNAL) +C +C LOCAL VARIABLES +C + INTEGER I,J + +C ---------- +C BEGIN CODE +C ---------- + + DO I=1,NEXTERNAL + DO J=0,3 + QP_P(J,I)=P(J,I) + ENDDO + ENDDO + + CALL ML5_0_MP_IMPROVE_PS_POINT_PRECISION(QP_P) + + DO I=1,NEXTERNAL + DO J=0,3 + P(J,I)=QP_P(J,I) + ENDDO + ENDDO + + END + + + SUBROUTINE ML5_0_MP_IMPROVE_PS_POINT_PRECISION(P) + IMPLICIT NONE +C +C CONSTANTS +C + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) +C +C ARGUMENTS +C + REAL*16 P(0:3,NEXTERNAL) +C +C LOCAL VARIABLES +C + INTEGER I,J + INTEGER ERRCODE,ERRCODETMP + REAL*16 NEWP(0:3,NEXTERNAL) +C +C FUNCTIONS +C + LOGICAL ML5_0_MP_IS_PHYSICAL +C +C SAVED VARIABLES +C + INCLUDE 'MadLoopParams.inc' +C +C SAVED VARIABLES +C + INTEGER WARNED + DATA WARNED/0/ + + LOGICAL TOLD_SUPPRESS + DATA TOLD_SUPPRESS/.FALSE./ +C ---------- +C BEGIN CODE +C ---------- + +C ERROR CODES CONVENTION +C +C 1 :: None physical PS point input +C 100-1000 :: Error in the origianl method for restoring +C precision +C 1000-9999 :: Error when restoring precision ala PSMC +C + ERRCODETMP=0 + ERRCODE=0 + + DO J=1,NEXTERNAL + DO I=0,3 + NEWP(I,J)=P(I,J) + ENDDO + ENDDO + +C Check the sanity of the original PS point + IF (.NOT.ML5_0_MP_IS_PHYSICAL(NEWP,WARNED)) THEN + ERRCODE = 1 + WRITE(*,*) 'ERROR:: The input PS point is not precise enough.' + GOTO 100 + ENDIF + +C Now restore the precision + IF (IMPROVEPSPOINT.EQ.1) THEN + CALL ML5_0_MP_PSMC_IMPROVE_PS_POINT_PRECISION(NEWP,ERRCODE + $ ,WARNED) + ELSEIF((IMPROVEPSPOINT.EQ.2).OR.(IMPROVEPSPOINT.LE.0)) THEN + CALL ML5_0_MP_ORIG_IMPROVE_PS_POINT_PRECISION(NEWP,ERRCODE + $ ,WARNED) + ENDIF + IF (ERRCODE.NE.0) THEN + IF (WARNED.LT.20) THEN + WRITE(*,*) 'INFO:: Attempting to rescue the precision' + $ //' improvement with an alternative method.' + WARNED=WARNED+1 + ENDIF + IF (IMPROVEPSPOINT.EQ.1) THEN + CALL ML5_0_MP_ORIG_IMPROVE_PS_POINT_PRECISION(NEWP + $ ,ERRCODETMP,WARNED) + ELSEIF((IMPROVEPSPOINT.EQ.2).OR.(IMPROVEPSPOINT.LE.0)) THEN + CALL ML5_0_MP_PSMC_IMPROVE_PS_POINT_PRECISION(NEWP + $ ,ERRCODETMP,WARNED) + ENDIF + IF (ERRCODETMP.NE.0) GOTO 100 + ENDIF + +C Report to the user or update the PS point. + + GOTO 101 + 100 CONTINUE + IF (WARNED.LT.20) THEN + WRITE(*,*) 'WARNING:: This PS point could not be improved.' + $ //' Error code = ',ERRCODE,ERRCODETMP + CALL ML5_0_MP_WRITE_MOM(P) + WARNED = WARNED +1 + ENDIF + GOTO 102 + 101 CONTINUE + DO J=1,NEXTERNAL + DO I=0,3 + P(I,J)=NEWP(I,J) + ENDDO + ENDDO + 102 CONTINUE + + IF (WARNED.GE.20.AND..NOT.TOLD_SUPPRESS) THEN + WRITE(*,*) 'INFO:: Further warnings from the improve_ps' + $ //' routine will now be supressed.' + TOLD_SUPPRESS=.TRUE. + ENDIF + + END + + + FUNCTION ML5_0_MP_IS_CLOSE(P,NEWP,WARNED) + IMPLICIT NONE +C +C CONSTANTS +C + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + REAL*16 ZERO + PARAMETER (ZERO=0.0E+00_16) + REAL*16 THRS_CLOSE + PARAMETER (THRS_CLOSE=1.0E-02_16) +C +C ARGUMENTS +C + REAL*16 P(0:3,NEXTERNAL), NEWP(0:3,NEXTERNAL) + LOGICAL ML5_0_MP_IS_CLOSE + INTEGER WARNED +C +C LOCAL VARIABLES +C + INTEGER I,J + REAL*16 REF,REF2 + DOUBLE PRECISION BUFFDP + +C NOW MAKE SURE THE SHIFTED POINT IS NOT TOO FAR FROM THE ORIGINAL +C ONE + ML5_0_MP_IS_CLOSE = .TRUE. + REF = ZERO + REF2 = ZERO + DO J=1,NEXTERNAL + DO I=0,3 + REF2 = REF2 + ABS(P(I,J)) + REF = REF + ABS(P(I,J)-NEWP(I,J)) + ENDDO + ENDDO + + IF ((REF/REF2).GT.THRS_CLOSE) THEN + ML5_0_MP_IS_CLOSE = .FALSE. + IF (WARNED.LT.20) THEN + BUFFDP = (REF/REF2) + WRITE(*,*) 'WARNING:: The improved PS point is too far from' + $ //' the original one',BUFFDP + WARNED=WARNED+1 + ENDIF + ENDIF + + END + + FUNCTION ML5_0_MP_IS_PHYSICAL(P,WARNED) + IMPLICIT NONE +C +C CONSTANTS +C + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INTEGER NINITIAL + PARAMETER (NINITIAL=2) + REAL*16 ZERO + PARAMETER (ZERO=0.0E+00_16) + REAL*16 MP__ZERO + PARAMETER (MP__ZERO=ZERO) + REAL*16 ONE + PARAMETER (ONE=1.0E+00_16) + REAL*16 TWO + PARAMETER (TWO=2.0E+00_16) + REAL*16 THRES_ONSHELL + PARAMETER (THRES_ONSHELL=1.0E-02_16) + REAL*16 THRES_FOURMOM + PARAMETER (THRES_FOURMOM=1.0E-06_16) +C +C ARGUMENTS +C + REAL*16 P(0:3,NEXTERNAL) + LOGICAL ML5_0_MP_IS_PHYSICAL + INTEGER WARNED +C +C LOCAL VARIABLES +C + INTEGER I,J + REAL*16 BUFF,REF + REAL*16 MASSES(NEXTERNAL) + DOUBLE PRECISION BUFFDPA,BUFFDPB +C +C GLOBAL VARIABLES +C + + INCLUDE 'mp_coupl.inc' + + MASSES(1)=MP__ZERO + MASSES(2)=MP__ZERO + MASSES(3)=MP__MDL_MT + MASSES(4)=MP__MDL_MT + +C ---------- +C BEGIN CODE +C ---------- + + ML5_0_MP_IS_PHYSICAL = .TRUE. + +C WE FIRST CHECK THAT THE INPUT PS POINT IS REASONABLY PHYSICAL +C FOR THAT WE NEED A REFERENCE SCALE + REF=ZERO + DO J=1,NEXTERNAL + REF=REF+ABS(P(0,J)) + ENDDO + DO I=0,3 + BUFF=ZERO + DO J=1,NINITIAL + BUFF=BUFF-P(I,J) + ENDDO + DO J=NINITIAL+1,NEXTERNAL + BUFF=BUFF+P(I,J) + ENDDO + IF ((BUFF/REF).GT.THRES_FOURMOM) THEN + IF (WARNED.LT.20) THEN + BUFFDPA = (BUFF/REF) + WRITE(*,*) 'ERROR:: Four-momentum conservation is not' + $ //' accurate enough, ',BUFFDPA + CALL ML5_0_MP_WRITE_MOM(P) + WARNED=WARNED+1 + ENDIF + ML5_0_MP_IS_PHYSICAL = .FALSE. + ENDIF + ENDDO + REF = REF / (ONE*NEXTERNAL) + DO I=1,NEXTERNAL + REF=ABS(P(0,I))+ABS(P(1,I))+ABS(P(2,I))+ABS(P(3,I)) + IF ((SQRT(ABS(P(0,I)**2-P(1,I)**2-P(2,I)**2-P(3,I)**2-MASSES(I) + $ **2))/REF).GT.THRES_ONSHELL) THEN + IF (WARNED.LT.20) THEN + BUFFDPA=MASSES(I) + BUFFDPB=(SQRT(ABS(P(0,I)**2-P(1,I)**2-P(2,I)**2-P(3,I)**2 + $ -MASSES(I)**2))/REF) + WRITE(*,*) 'ERROR:: Onshellness of the momentum of' + $ //' particle ',I,' of mass ',BUFFDPA,' is not accurate' + $ //' enough, ',BUFFDPB + CALL ML5_0_MP_WRITE_MOM(P) + WARNED=WARNED+1 + ENDIF + ML5_0_MP_IS_PHYSICAL = .FALSE. + ENDIF + ENDDO + + END + + SUBROUTINE ML5_0_WRITE_MOM(P) + IMPLICIT NONE + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INTEGER NINITIAL + PARAMETER (NINITIAL=2) + DOUBLE PRECISION ZERO + PARAMETER (ZERO=0.0D0) + DOUBLE PRECISION ML5_0_MDOT + + INTEGER I,J + +C +C ARGUMENTS +C + DOUBLE PRECISION P(0:3,NEXTERNAL),PSUM(0:3) + DO I=0,3 + PSUM(I)=ZERO + DO J=1,NINITIAL + PSUM(I)=PSUM(I)+P(I,J) + ENDDO + DO J=NINITIAL+1,NEXTERNAL + PSUM(I)=PSUM(I)-P(I,J) + ENDDO + ENDDO + WRITE (*,*) ' Phase space point:' + WRITE (*,*) ' ---------------------' + WRITE (*,*) ' E | px | py | pz | m ' + DO I=1,NEXTERNAL + WRITE (*,'(1x,5e27.17)') P(0,I),P(1,I),P(2,I),P(3,I) + $ ,SQRT(ABS(ML5_0_MDOT(P(0,I),P(0,I)))) + ENDDO + WRITE (*,*) ' Four-momentum conservation sum:' + WRITE (*,'(1x,4e27.17)') PSUM(0),PSUM(1),PSUM(2),PSUM(3) + WRITE (*,*) ' ---------------------' + END + + DOUBLE PRECISION FUNCTION ML5_0_MDOT(P1,P2) + IMPLICIT NONE + DOUBLE PRECISION P1(0:3),P2(0:3) + ML5_0_MDOT=P1(0)*P2(0)-P1(1)*P2(1)-P1(2)*P2(2)-P1(3)*P2(3) + RETURN + END + + SUBROUTINE ML5_0_MP_WRITE_MOM(P) + IMPLICIT NONE + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INTEGER NINITIAL + PARAMETER (NINITIAL=2) + REAL*16 ZERO + PARAMETER (ZERO=0.0E+00_16) + REAL*16 ML5_0_MP_MDOT + + INTEGER I,J + +C +C ARGUMENTS +C + REAL*16 P(0:3,NEXTERNAL),PSUM(0:3),DOT + DOUBLE PRECISION DP_P(0:3,NEXTERNAL),DP_PSUM(0:3),DP_DOT + + DO I=0,3 + PSUM(I)=ZERO + DO J=1,NINITIAL + PSUM(I)=PSUM(I)+P(I,J) + ENDDO + DO J=NINITIAL+1,NEXTERNAL + PSUM(I)=PSUM(I)-P(I,J) + ENDDO + ENDDO + +C The GCC4.7 compiler on SLC machines has trouble to write out +C quadruple precision variable with the write(*,*) statement. I +C therefore perform the cast by hand + DO I=0,3 + DP_PSUM(I)=PSUM(I) + DO J=1,NEXTERNAL + DP_P(I,J)=P(I,J) + ENDDO + ENDDO + + WRITE (*,*) ' Phase space point:' + WRITE (*,*) ' ---------------------' + WRITE (*,*) ' E | px | py | pz | m ' + DO I=1,NEXTERNAL + DOT=SQRT(ABS(ML5_0_MP_MDOT(P(0,I),P(0,I)))) + DP_DOT=DOT + WRITE (*,'(1x,5e27.17)') DP_P(0,I),DP_P(1,I),DP_P(2,I),DP_P(3 + $ ,I),DP_DOT + ENDDO + WRITE (*,*) ' Four-momentum conservation sum:' + WRITE (*,'(1x,4e27.17)') DP_PSUM(0),DP_PSUM(1),DP_PSUM(2) + $ ,DP_PSUM(3) + WRITE (*,*) ' ---------------------' + END + + REAL*16 FUNCTION ML5_0_MP_MDOT(P1,P2) + IMPLICIT NONE + REAL*16 P1(0:3),P2(0:3) + ML5_0_MP_MDOT=P1(0)*P2(0)-P1(1)*P2(1)-P1(2)*P2(2)-P1(3)*P2(3) + RETURN + END + +C Rotate_PS rotates the PS point PS (without modifying it) +C stores the result in P and for the quadruple precision +C version , it also modifies the global variables +C PS and MP_DONE accordingly. + + SUBROUTINE ML5_0_ROTATE_PS(P_IN,P,ROTATION) + IMPLICIT NONE +C +C CONSTANTS +C + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) +C +C ARGUMENTS +C + DOUBLE PRECISION P_IN(0:3,NEXTERNAL),P(0:3,NEXTERNAL) + INTEGER ROTATION +C +C LOCAL VARIABLES +C + INTEGER I,J + +C ---------- +C BEGIN CODE +C ---------- + + DO I=1,NEXTERNAL +C rotation=1 => (xp=z,yp=-x,zp=-y) + IF(ROTATION.EQ.1) THEN + P(0,I)=P_IN(0,I) + P(1,I)=P_IN(3,I) + P(2,I)=-P_IN(1,I) + P(3,I)=-P_IN(2,I) +C rotation=2 => (xp=-z,yp=y,zp=x) + ELSEIF(ROTATION.EQ.2) THEN + P(0,I)=P_IN(0,I) + P(1,I)=-P_IN(3,I) + P(2,I)=P_IN(2,I) + P(3,I)=P_IN(1,I) + ELSE + P(0,I)=P_IN(0,I) + P(1,I)=P_IN(1,I) + P(2,I)=P_IN(2,I) + P(3,I)=P_IN(3,I) + ENDIF + ENDDO + + END + + + SUBROUTINE ML5_0_MP_ROTATE_PS(P_IN,P,ROTATION) + IMPLICIT NONE +C +C CONSTANTS +C + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) +C +C ARGUMENTS +C + REAL*16 P_IN(0:3,NEXTERNAL),P(0:3,NEXTERNAL) + INTEGER ROTATION +C +C LOCAL VARIABLES +C + INTEGER I,J +C +C GLOBAL VARIABLES +C + LOGICAL MP_DONE + COMMON/ML5_0_MP_DONE/MP_DONE + +C ---------- +C BEGIN CODE +C ---------- + + DO I=1,NEXTERNAL +C rotation=1 => (xp=z,yp=-x,zp=-y) + IF(ROTATION.EQ.1) THEN + P(0,I)=P_IN(0,I) + P(1,I)=P_IN(3,I) + P(2,I)=-P_IN(1,I) + P(3,I)=-P_IN(2,I) +C rotation=2 => (xp=-z,yp=y,zp=x) + ELSEIF(ROTATION.EQ.2) THEN + P(0,I)=P_IN(0,I) + P(1,I)=-P_IN(3,I) + P(2,I)=P_IN(2,I) + P(3,I)=P_IN(1,I) + ELSE + P(0,I)=P_IN(0,I) + P(1,I)=P_IN(1,I) + P(2,I)=P_IN(2,I) + P(3,I)=P_IN(3,I) + ENDIF + ENDDO + + MP_DONE = .FALSE. + + END + +C ***************************************************************** +C Beginning of the routine for restoring precision with V.H. method +C ***************************************************************** + + SUBROUTINE ML5_0_MP_ORIG_IMPROVE_PS_POINT_PRECISION(P,ERRCODE + $ ,WARNED) + IMPLICIT NONE +C +C CONSTANTS +C + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INTEGER NINITIAL + PARAMETER (NINITIAL=2) + REAL*16 ZERO + PARAMETER (ZERO=0.0E+00_16) + REAL*16 MP__ZERO + PARAMETER (MP__ZERO=ZERO) + REAL*16 ONE + PARAMETER (ONE=1.0E+00_16) + REAL*16 TWO + PARAMETER (TWO=2.0E+00_16) + REAL*16 THRS_TEST + PARAMETER (THRS_TEST=1.0E-15_16) +C +C ARGUMENTS +C + REAL*16 P(0:3,NEXTERNAL) + INTEGER ERRCODE, WARNED +C +C FUNCTIONS +C + LOGICAL ML5_0_MP_IS_CLOSE +C +C LOCAL VARIABLES +C + INTEGER I,J, P1, P2 +C PT STANDS FOR PTOT + REAL*16 PT(0:3), NEWP(0:3,NEXTERNAL) + REAL*16 BUFF,REF,REF2,DISCR + REAL*16 MASSES(NEXTERNAL) + REAL*16 SHIFTE(2),SHIFTZ(2) +C +C GLOBAL VARIABLES +C + + INCLUDE 'mp_coupl.inc' + + MASSES(1)=MP__ZERO + MASSES(2)=MP__ZERO + MASSES(3)=MP__MDL_MT + MASSES(4)=MP__MDL_MT + +C ---------- +C BEGIN CODE +C ---------- + ERRCODE = 0 + +C NOW WE MAKE SURE THAT THE PS POINT CAN BE IMPROVED BY THE +C ALGORITHM + REF=ZERO + DO J=1,NEXTERNAL + REF=REF+ABS(P(0,J)) + ENDDO + + IF (NINITIAL.NE.2) ERRCODE = 100 + + IF (ABS(P(1,1)/REF).GT.THRS_TEST.OR.ABS(P(2,1)/REF) + $ .GT.THRS_TEST.OR.ABS(P(1,2)/REF).GT.THRS_TEST.OR.ABS(P(2,2)/REF) + $ .GT.THRS_TEST) ERRCODE = 200 + + IF (MASSES(1).NE.ZERO.OR.MASSES(2).NE.ZERO) ERRCODE = 300 + + DO I=1,NEXTERNAL + IF (P(0,I).LT.ZERO) ERRCODE = 400 + I + ENDDO + + IF (ERRCODE.NE.0) GOTO 100 + +C WE FIRST SHIFT ALL THE FINAL STATE PARTICLES TO MAKE THEM +C EXACTLY ONSHELL + + DO I=0,3 + PT(I)=ZERO + ENDDO + DO I=NINITIAL+1,NEXTERNAL + DO J=0,3 + IF (J.EQ.3) THEN + NEWP(3,I)=SIGN(SQRT(ABS(P(0,I)**2-P(1,I)**2-P(2,I)**2 + $ -MASSES(I)**2)),P(3,I)) + ELSE + NEWP(J,I)=P(J,I) + ENDIF + PT(J)=PT(J)+NEWP(J,I) + ENDDO + ENDDO + +C WE CHOOSE P1 IN THE ALGORITHM TO ALWAYS BE THE PARTICLE WITH +C POSITIVE PZ + IF (P(3,1).GT.ZERO) THEN + P1=1 + P2=2 + ELSEIF (P(3,2).GT.ZERO) THEN + P1=2 + P2=1 + ELSE + ERRCODE = 500 + GOTO 100 + ENDIF + +C Now we calculate the shift to bring to P1 and P2 +C Mathematica gives +C ptotC = {ptotE, ptotX, ptotY, ptotZ}; +C pm1C = {pm1E + sm1E, pm1X, pm1Y, pm1Z + sm1Z}; +C {pm0E + sm0E, ptotX - pm1X, ptotY - pm1Y, pm0Z + sm0Z}; +C sol = Solve[{ptotC[[1]] - pm1C[[1]] - pm0C[[1]] == 0, +C ptotC[[4]] - pm1C[[4]] - pm0C[[4]] == 0, +C pm1C[[1]]^2 - pm1C[[2]]^2 - pm1C[[3]]^2 - pm1C[[4]]^2 == m1M^2, +C pm0C[[1]]^2 - pm0C[[2]]^2 - pm0C[[3]]^2 - pm0C[[4]]^2 == m2M^2}, +C {sm1E, sm1Z, sm0E, sm0Z}] // FullSimplify; +C (solC[[1]] /. {m1M -> 0, m2M -> 0} /. {pm1X -> 0, pm1Y -> 0}) +C END +C + DISCR = -PT(0)**2 + PT(1)**2 + PT(2)**2 + PT(3)**2 + IF (DISCR.LT.ZERO) DISCR = -DISCR + + SHIFTE(1) = (PT(0)*(-TWO*P(0,P1)*PT(0) + PT(0)**2 + PT(1)**2 + + $ PT(2)**2) + (TWO*P(0,P1) - PT(0))*PT(3)**2 + PT(3)*DISCR)/(TWO + $ *(PT(0) - PT(3))*(PT(0) + PT(3))) + SHIFTE(2) = -(PT(0)*(TWO*P(0,P2)*PT(0) - PT(0)**2 + PT(1)**2 + + $ PT(2)**2) + (-TWO*P(0,P2) + PT(0))*PT(3)**2 + PT(3)*DISCR) + $ /(TWO*(PT(0) - PT(3))*(PT(0) + PT(3))) + SHIFTZ(1) = (-TWO*P(3,P1)*(PT(0)**2 - PT(3)**2) + PT(3)*(PT(0)* + $ *2 + PT(1)**2 + PT(2)**2 - PT(3)**2) + PT(0)*DISCR)/(TWO*(PT(0) + $ **2 - PT(3)**2)) + SHIFTZ(2) = -(TWO*P(3,P2)*(PT(0)**2 - PT(3)**2) + PT(3)*(-PT(0)* + $ *2 + PT(1)**2 + PT(2)**2 + PT(3)**2) + PT(0)*DISCR)/(TWO*(PT(0) + $ **2 - PT(3)**2)) + NEWP(0,P1) = P(0,P1)+SHIFTE(1) + NEWP(3,P1) = P(3,P1)+SHIFTZ(1) + NEWP(0,P2) = P(0,P2)+SHIFTE(2) + NEWP(3,P2) = P(3,P2)+SHIFTZ(2) + NEWP(1,P2) = P(1,P2) + NEWP(2,P2) = P(2,P2) + DO J=1,2 + REF=ZERO + DO I=NINITIAL+1,NEXTERNAL + REF = REF + P(J,I) + ENDDO + REF = REF - P(J,P2) + NEWP(J,P1) = REF + ENDDO + + IF (.NOT.ML5_0_MP_IS_CLOSE(P,NEWP,WARNED)) THEN + ERRCODE=999 + GOTO 100 + ENDIF + + DO J=1,NEXTERNAL + DO I=0,3 + P(I,J)=NEWP(I,J) + ENDDO + ENDDO + + 100 CONTINUE + + END + +C ***************************************************************** +C Beginning of the routine for restoring precision a la PSMC +C ***************************************************************** + + SUBROUTINE ML5_0_MP_PSMC_IMPROVE_PS_POINT_PRECISION(P,ERRCODE + $ ,WARNED) + IMPLICIT NONE +C +C CONSTANTS +C + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INTEGER NINITIAL + PARAMETER (NINITIAL=2) + REAL*16 ZERO + PARAMETER (ZERO=0.0E+00_16) + REAL*16 MP__ZERO + PARAMETER (MP__ZERO=ZERO) + REAL*16 ONE + PARAMETER (ONE=1.0E+00_16) + REAL*16 TWO + PARAMETER (TWO=2.0E+00_16) + REAL*16 CONSISTENCY_THRES + PARAMETER (CONSISTENCY_THRES=1.0E-25_16) + + INTEGER NAPPROXZEROS + PARAMETER (NAPPROXZEROS=3) + +C +C ARGUMENTS +C + REAL*16 P(0:3,NEXTERNAL) + INTEGER ERRCODE,ERROR,WARNED +C +C FUNCTIONS +C + LOGICAL ML5_0_MP_IS_CLOSE +C +C LOCAL VARIABLES +C + INTEGER I,J, P1, P2 + REAL*16 NEWP(0:3,NEXTERNAL), PBUFF(0:3) + REAL*16 BUFF, BUFF2, XSCALE, APPROX_ZEROS(NAPPROXZEROS) + REAL*16 MASSES(NEXTERNAL) +C +C GLOBAL VARIABLES +C + + INCLUDE 'mp_coupl.inc' + +C ---------- +C BEGIN CODE +C ---------- + + MASSES(1)=MP__ZERO + MASSES(2)=MP__ZERO + MASSES(3)=MP__MDL_MT + MASSES(4)=MP__MDL_MT + + ERRCODE = 0 + XSCALE = ONE + +C Define the seeds which should be tried + APPROX_ZEROS(1)=1.0E+00_16 + APPROX_ZEROS(2)=1.1E+00_16 + APPROX_ZEROS(3)=0.9E+00_16 + +C Start by copying the momenta + DO I=1,NEXTERNAL + DO J=0,3 + NEWP(J,I)=P(J,I) + ENDDO + ENDDO + +C First make sur that the space like momentum is exactly conserved + DO J=0,3 + PBUFF(J)=ZERO + ENDDO + DO I=1,NINITIAL + DO J=1,3 + PBUFF(J)=PBUFF(J)+NEWP(J,I) + ENDDO + ENDDO + DO I=NINITIAL+1,NEXTERNAL-1 + DO J=1,3 + PBUFF(J)=PBUFF(J)-NEWP(J,I) + ENDDO + ENDDO + DO J=1,3 + NEWP(J,NEXTERNAL)=PBUFF(J) + ENDDO + +C Now find the 'x' rescaling factor + DO I=1,NAPPROXZEROS + CALL ML5_0_FINDX(NEWP,APPROX_ZEROS(I),XSCALE,ERROR) + IF(ERROR.EQ.0) THEN + GOTO 1001 + ELSE + ERRCODE=ERRCODE+(10**(I-1))*ERROR + ENDIF + ENDDO + IF (WARNED.LT.20) THEN + WRITE(*,*) 'WARNING:: Could not find the proper rescaling' + $ //' factor x. Restoring precision ala PSMC will therefore not' + $ //' be used.' + WARNED=WARNED+1 + ENDIF + IF (ERRCODE.LT.1000) THEN + ERRCODE=ERRCODE+1000 + ENDIF + GOTO 1000 + 1001 CONTINUE + ERRCODE = 0 + +C Apply the rescaling + DO I=1,NEXTERNAL + DO J=1,3 +C Consider scaling by x**2 for the first particle so that +C the algorithm for numerically solving for XSCALE has a +C non-vanishing +C derivative in the case that all particle are massless. + IF (I.EQ.1) THEN + NEWP(J,I)=NEWP(J,I)*XSCALE**2 + ELSE + NEWP(J,I)=NEWP(J,I)*XSCALE + ENDIF + ENDDO + ENDDO + +C Now restore exact onshellness of the particles. + DO I=1,NEXTERNAL + BUFF=MASSES(I)**2 + DO J=1,3 + BUFF=BUFF+NEWP(J,I)**2 + ENDDO + NEWP(0,I)=SQRT(BUFF) + ENDDO + +C Consistency check + BUFF=ZERO + BUFF2=ZERO + DO I=1,NINITIAL + BUFF=BUFF-NEWP(0,I) + BUFF2=BUFF2+NEWP(0,I) + ENDDO + DO I=NINITIAL+1,NEXTERNAL + BUFF=BUFF+NEWP(0,I) + BUFF2=BUFF2+NEWP(0,I) + ENDDO + IF ((ABS(BUFF)/BUFF2).GT.CONSISTENCY_THRES) THEN + IF (WARNED.LT.20) THEN + WRITE(*,*) 'WARNING:: The consistency check in the a la PSMC' + $ //' precision restoring algorithm failed. The result will' + $ //' therefore not be used.' + WARNED=WARNED+1 + ENDIF + ERRCODE = 1000 + GOTO 1000 + ENDIF + + IF (.NOT.ML5_0_MP_IS_CLOSE(P,NEWP,WARNED)) THEN + ERRCODE=999 + GOTO 1000 + ENDIF + + DO J=1,NEXTERNAL + DO I=0,3 + P(I,J)=NEWP(I,J) + ENDDO + ENDDO + + 1000 CONTINUE + + END + + + SUBROUTINE ML5_0_FINDX(P,SEED,XSCALE,ERROR) + IMPLICIT NONE +C +C CONSTANTS +C + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INTEGER NINITIAL + PARAMETER (NINITIAL=2) + REAL*16 ZERO + PARAMETER (ZERO=0.0E+00_16) + REAL*16 MP__ZERO + PARAMETER (MP__ZERO=ZERO) + REAL*16 ONE + PARAMETER (ONE=1.0E+00_16) + REAL*16 TWO + PARAMETER (TWO=2.0E+00_16) + INTEGER MAXITERATIONS + PARAMETER (MAXITERATIONS=8) + REAL*16 CONVERGED + PARAMETER (CONVERGED=1.0E-26_16) +C +C ARGUMENTS +C + REAL*16 P(0:3,NEXTERNAL),SEED,XSCALE + INTEGER ERROR +C +C LOCAL VARIABLES +C + INTEGER I,J,ERR + REAL*16 PVECSQ(NEXTERNAL) + REAL*16 XN, XNP1,FVAL,DVAL + +C ---------- +C BEGIN CODE +C ---------- + + ERROR = 0 + XSCALE = SEED + XN = SEED + XNP1 = SEED + + DO I=1,NEXTERNAL + PVECSQ(I)=P(1,I)**2+P(2,I)**2+P(3,I)**2 + ENDDO + + DO I=1,MAXITERATIONS + CALL ML5_0_FUNCT(PVECSQ(1),XN,.FALSE.,ERR, FVAL) + IF (ERR.NE.0) THEN + ERROR=ERR + GOTO 710 + ENDIF + CALL ML5_0_FUNCT(PVECSQ(1),XN,.TRUE.,ERR, DVAL) + IF (ERR.NE.0) THEN + ERROR=ERR + GOTO 710 + ENDIF + XNP1=XN-(FVAL/DVAL) + IF((ABS(((XNP1-XN)*TWO)/(XNP1+XN))).LT.CONVERGED) THEN + XN=XNP1 + GOTO 700 + ENDIF + XN=XNP1 + ENDDO + ERROR=9 + GOTO 710 + + 700 CONTINUE +C For good measure, we iterate one last time + CALL ML5_0_FUNCT(PVECSQ(1),XN,.FALSE.,ERR, FVAL) + IF (ERR.NE.0) THEN + ERROR=ERR + GOTO 710 + ENDIF + CALL ML5_0_FUNCT(PVECSQ(1),XN,.TRUE.,ERR, DVAL) + IF (ERR.NE.0) THEN + ERROR=ERR + GOTO 710 + ENDIF + + XSCALE=XN-(FVAL/DVAL) + + 710 CONTINUE + + END + + SUBROUTINE ML5_0_FUNCT(PVECSQ,X,DERIVATIVE,ERROR,RES) + IMPLICIT NONE +C +C CONSTANTS +C + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INTEGER NINITIAL + PARAMETER (NINITIAL=2) + REAL*16 ZERO + PARAMETER (ZERO=0.0E+00_16) + REAL*16 MP__ZERO + PARAMETER (MP__ZERO=ZERO) + REAL*16 ONE + PARAMETER (ONE=1.0E+00_16) + REAL*16 TWO + PARAMETER (TWO=2.0E+00_16) +C +C ARGUMENTS +C + REAL*16 PVECSQ(NEXTERNAL),X,RES + INTEGER ERROR + LOGICAL DERIVATIVE +C +C LOCAL VARIABLES +C + INTEGER I,J + REAL*16 BUFF,FACTOR + REAL*16 MASSES(NEXTERNAL) +C +C GLOBAL VARIABLES +C + + INCLUDE 'mp_coupl.inc' + +C ---------- +C BEGIN CODE +C ---------- + + MASSES(1)=MP__ZERO + MASSES(2)=MP__ZERO + MASSES(3)=MP__MDL_MT + MASSES(4)=MP__MDL_MT + + ERROR=0 + RES=ZERO + BUFF=ZERO + +C Consider scaling by x**2 for the first particle so that +C the algorithm for numerically solving for XSCALE has a +C non-vanishing +C derivative in the case that all particle are massless. + + DO I=1,NEXTERNAL + IF (I.LE.NINITIAL) THEN + FACTOR=-ONE + ELSE + FACTOR=ONE + ENDIF + IF (I.EQ.1) THEN + BUFF=MASSES(I)**2+PVECSQ(I)*X**4 + ELSE + BUFF=MASSES(I)**2+PVECSQ(I)*X**2 + ENDIF + IF (BUFF.LT.ZERO) THEN + RES=ZERO + ERROR = 1 + GOTO 800 + ENDIF + IF (DERIVATIVE) THEN + IF (I.EQ.1) THEN + RES=RES + FACTOR*((2*X*PVECSQ(I))/SQRT(BUFF)) + ELSE + RES=RES + FACTOR*((X*PVECSQ(I))/SQRT(BUFF)) + ENDIF + ELSE + RES=RES + FACTOR*SQRT(BUFF) + ENDIF + ENDDO + + 800 CONTINUE + + END + diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/loop_matrix.f b/UNITTEST_proc/SubProcesses/P0_gg_ttx/loop_matrix.f new file mode 100644 index 0000000000..a99f72d8cd --- /dev/null +++ b/UNITTEST_proc/SubProcesses/P0_gg_ttx/loop_matrix.f @@ -0,0 +1,1860 @@ + SUBROUTINE ML5_0_SLOOPMATRIXHEL(P,HEL,ANS) + USE ALOHA_OBJECT + IMPLICIT NONE +C +C CONSTANTS +C + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + + INCLUDE 'nsquaredSO.inc' + +C +C ARGUMENTS +C + REAL*8 P(0:3,NEXTERNAL) + REAL*8 ANS(0:3,0:NSQUAREDSO) + INTEGER HEL, USERHEL + COMMON/ML5_0_USERCHOICE/USERHEL +C ---------- +C BEGIN CODE +C ---------- + USERHEL=HEL + CALL ML5_0_SLOOPMATRIX(P,ANS) + END + + LOGICAL FUNCTION ML5_0_IS_HEL_SELECTED(HELID) + IMPLICIT NONE +C +C CONSTANTS +C + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INTEGER NCOMB + PARAMETER (NCOMB=16) +C +C ARGUMENTS +C + INTEGER HELID +C +C LOCALS +C + INTEGER I,J + LOGICAL FOUNDIT +C +C GLOBALS +C + INTEGER HELC(NEXTERNAL,NCOMB) + COMMON/ML5_0_HELCONFIGS/HELC + + INTEGER POLARIZATIONS(0:NEXTERNAL,0:5) + COMMON/ML5_0_BEAM_POL/POLARIZATIONS +C ---------- +C BEGIN CODE +C ---------- + + ML5_0_IS_HEL_SELECTED = .TRUE. + IF (POLARIZATIONS(0,0).EQ.-1) THEN + RETURN + ENDIF + + DO I=1,NEXTERNAL + IF (POLARIZATIONS(I,0).EQ.-1) THEN + CYCLE + ENDIF + FOUNDIT = .FALSE. + DO J=1,POLARIZATIONS(I,0) + IF (HELC(I,HELID).EQ.POLARIZATIONS(I,J)) THEN + FOUNDIT = .TRUE. + EXIT + ENDIF + ENDDO + IF(.NOT.FOUNDIT) THEN + ML5_0_IS_HEL_SELECTED = .FALSE. + RETURN + ENDIF + ENDDO + RETURN + + END + + LOGICAL FUNCTION ML5_0_ISZERO(TOTEST, REFERENCE_VALUE, AMPLN) + IMPLICIT NONE +C +C CONSTANTS +C + INTEGER NLOOPAMPS + PARAMETER (NLOOPAMPS=129) +C +C ARGUMENTS +C + REAL*8 TOTEST, REFERENCE_VALUE + INTEGER AMPLN +C +C GLOBAL +C + INCLUDE 'MadLoopParams.inc' + + COMPLEX*16 AMPL(3,NLOOPAMPS) + LOGICAL S(NLOOPAMPS) + COMMON/ML5_0_AMPL/AMPL,S +C ---------- +C BEGIN CODE +C ---------- + IF(ABS(REFERENCE_VALUE).EQ.0.0D0) THEN + ML5_0_ISZERO=.FALSE. + WRITE(*,*) '##E02 ERRROR Reference value for comparison is' + $ //' zero.' + STOP + ELSE + ML5_0_ISZERO=((ABS(TOTEST)/ABS(REFERENCE_VALUE)).LT.ZEROTHRES) + ENDIF + IF(AMPLN.NE.-1) THEN + IF((.NOT.ML5_0_ISZERO).AND.(.NOT.S(AMPLN))) THEN + WRITE(*,*) '##W01 WARNING Contribution ',AMPLN,' is detected' + $ //' as contributing with CR=',(ABS(TOTEST) + $ /ABS(REFERENCE_VALUE)),' but is unstable.' + ENDIF + ENDIF + + END + + SUBROUTINE ML5_0_SLOOPMATRIX(P_USER,ANSRETURNED) + USE ALOHA_OBJECT +C +C Generated by MadGraph5_aMC@NLO v. 3.7.2, 2026-04-29 +C By the MadGraph5_aMC@NLO Development Team +C Visit launchpad.net/madgraph5 and amcatnlo.web.cern.ch +C +C Returns amplitude squared summed/avg over colors +C and helicities for the point in phase space P(0:3,NEXTERNAL) +C and external lines W(0:6,NEXTERNAL) +C +C Process: g g > t t~ QCD<=2 QED=0 [ virt = QCD ] +C + IMPLICIT NONE +C +C CONSTANTS +C + CHARACTER*512 PARAMFNAME,HELCONFIGFNAME,LOOPFILTERFNAME + CHARACTER*512 COLORNUMFNAME,COLORDENOMFNAME, HELFILTERFNAME + CHARACTER*512 PROC_PREFIX + PARAMETER ( PARAMFNAME='MadLoopParams.dat') + PARAMETER ( HELCONFIGFNAME='HelConfigs.dat') + PARAMETER ( LOOPFILTERFNAME='LoopFilter.dat') + PARAMETER ( HELFILTERFNAME='HelFilter.dat') + PARAMETER ( COLORNUMFNAME='ColorNumFactors.dat') + PARAMETER ( COLORDENOMFNAME='ColorDenomFactors.dat') + PARAMETER ( PROC_PREFIX='ML5_0_') + + INTEGER NBORNAMPS + PARAMETER (NBORNAMPS=3) + INTEGER NLOOPAMPS, NCTAMPS + PARAMETER (NLOOPAMPS=129, NCTAMPS=85) + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INTEGER NINITIAL + PARAMETER (NINITIAL=2) + INTEGER NWAVEFUNCS + PARAMETER (NWAVEFUNCS=10) + INTEGER NCOMB + PARAMETER (NCOMB=16) + REAL*8 ZERO + PARAMETER (ZERO=0D0) + REAL*16 MP__ZERO + PARAMETER (MP__ZERO=0E0_16) + COMPLEX*16 IMAG1 + PARAMETER (IMAG1=(0D0,1D0)) +C This parameter is designed for the check timing command of MG5 + LOGICAL SKIPLOOPEVAL + PARAMETER (SKIPLOOPEVAL=.FALSE.) + LOGICAL BOOTANDSTOP + PARAMETER (BOOTANDSTOP=.FALSE.) + INCLUDE 'nsquaredSO.inc' + INTEGER NSQUAREDSOP1 + PARAMETER (NSQUAREDSOP1=NSQUAREDSO+1) + INTEGER MAXSTABILITYLENGTH + DATA MAXSTABILITYLENGTH/20/ + COMMON/ML5_0_STABILITY_TESTS/MAXSTABILITYLENGTH +C +C ARGUMENTS +C + REAL*8 P_USER(0:3,NEXTERNAL) + REAL*8 ANSRETURNED(0:3,0:NSQUAREDSO) +C +C LOCAL VARIABLES +C + REAL*8 ANS(0:3) + INTEGER I,J,K,H + + CHARACTER*512 PARAMFN,HELCONFIGFN,LOOPFILTERFN,COLORNUMFN + $ ,COLORDENOMFN,HELFILTERFN + CHARACTER*512 TMP + SAVE PARAMFN + SAVE HELCONFIGFN + SAVE LOOPFILTERFN + SAVE COLORNUMFN + SAVE COLORDENOMFN + SAVE HELFILTERFN + + INTEGER HELPICKED_BU, CTMODEINIT_BU + REAL*8 MLSTABTHRES_BU +C P is the actual PS POINT used for the computation, and can be +C rotated for the stability test purposes. + REAL*8 P(0:3,NEXTERNAL) +C DP_RES STORES THE DOUBLE PRECISION RESULT OBTAINED FROM +C DIFFERENT EVALUATION METHODS IN ORDER TO ASSESS STABILITY. +C THE STAB_STAGE COUNTER I CORRESPONDANCE GOES AS FOLLOWS +C I=1 -> ORIGINAL PS, CTMODE=1 +C I=2 -> ORIGINAL PS, CTMODE=2, (ONLY WITH CTMODERUN=-1) +C I=3 -> PS WITH ROTATION 1, CTMODE=1, (ONLY WITH CTMODERUN=-2) +C I=4 -> PS WITH ROTATION 2, CTMODE=1, (ONLY WITH CTMODERUN=-3) +C I=5 -> POSSIBLY MORE EVALUATION METHODS IN THE FUTURE, MAX IS +C MAXSTABILITYLENGTH +C IF UNSTABLE IT GOES TO THE SAME PATTERN BUT STAB_INDEX IS THEN +C I+20. + LOGICAL EVAL_DONE(MAXSTABILITYLENGTH) + LOGICAL DOING_QP_EVALS + INTEGER STAB_INDEX,BASIC_CT_MODE + INTEGER N_DP_EVAL, N_QP_EVAL + DATA N_DP_EVAL/1/ + DATA N_QP_EVAL/1/ +C This is used for loop-induced where the reference scale for +C comparisons is infered from +C the previous points + REAL*8 NEXTREF + DATA NEXTREF/ZERO/ + INTEGER NPSPOINTS + DATA NPSPOINTS/0/ + LOGICAL FOUND_VALID_REDUCTION_METHOD + DATA FOUND_VALID_REDUCTION_METHOD/.FALSE./ + + REAL*8 ACC + REAL*8 DP_RES(3,MAXSTABILITYLENGTH) +C QP_RES STORES THE QUADRUPLE PRECISION RESULT OBTAINED FROM +C DIFFERENT EVALUATION METHODS IN ORDER TO ASSESS STABILITY. + REAL*8 QP_RES(3,MAXSTABILITYLENGTH) + INTEGER NHEL(NEXTERNAL), IC(NEXTERNAL) + INTEGER NATTEMPTS + DATA NATTEMPTS/0/ + DATA IC/NEXTERNAL*1/ + INTEGER FLAVOR(NEXTERNAL) + DATA FLAVOR /NEXTERNAL*1/ + REAL*8 BUFFR(3),TEMP(3),TEMP1,TEMP2 + COMPLEX*16 CFTOT + LOGICAL FOUNDHELFILTER,FOUNDLOOPFILTER + DATA FOUNDHELFILTER/.TRUE./ + DATA FOUNDLOOPFILTER/.TRUE./ + INTEGER IDEN + DATA IDEN/256/ + INTEGER HELAVGFACTOR + DATA HELAVGFACTOR/4/ +C For a 1>N process, them BEAMTWO_HELAVGFACTOR would be set to 1. + INTEGER BEAMS_HELAVGFACTOR(2) + DATA (BEAMS_HELAVGFACTOR(I),I=1,2)/2,2/ + LOGICAL DONEHELDOUBLECHECK + DATA DONEHELDOUBLECHECK/.FALSE./ + INTEGER NEPS + DATA NEPS/0/ +C Below are variables to bypass the checkphase and insure +C stability check to take place + LOGICAL OLD_CHECKPHASE, OLD_HELDOUBLECHECKED + LOGICAL OLD_GOODHEL(NCOMB) + LOGICAL OLD_GOODAMP(NLOOPAMPS,NCOMB) + + LOGICAL BYPASS_CHECK, ALWAYS_TEST_STABILITY + COMMON/ML5_0_BYPASS_CHECK/BYPASS_CHECK, ALWAYS_TEST_STABILITY +C +C FUNCTIONS +C + LOGICAL ML5_0_ISZERO + LOGICAL ML5_0_IS_HEL_SELECTED +C +C GLOBAL VARIABLES +C + INCLUDE 'process_info.inc' + INCLUDE 'coupl.inc' + INCLUDE 'mp_coupl.inc' + INCLUDE 'MadLoopParams.inc' + + INTEGER NTRY + DATA NTRY/0/ + LOGICAL CHECKPHASE + DATA CHECKPHASE/.TRUE./ + LOGICAL HELDOUBLECHECKED + DATA HELDOUBLECHECKED/.FALSE./ + REAL*8 REF + DATA REF/0.0D0/ + COMMON/ML5_0_INIT/NTRY,CHECKPHASE,HELDOUBLECHECKED,REF + +C THE LOGICAL BELOWS ARE JUST TO KEEP TRACK OF WHETHER THE MP_PS +C HAS BEEN SET YET OR NOT AND WHETER THE MP EXTERNAL WFS HAVE +C BEEN COMPUTED YET. + LOGICAL MP_DONE + DATA MP_DONE/.FALSE./ + COMMON/ML5_0_MP_DONE/MP_DONE + LOGICAL MP_PS_SET + DATA MP_PS_SET/.FALSE./ + COMMON/ML5_0_MP_PS_SET/MP_PS_SET + +C PS CAN POSSIBILY BE PASSED THROUGH IMPROVE_PS BUT IS NOT +C MODIFIED FOR THE PURPOSE OF THE STABILITY TEST +C EVEN THOUGH THEY ARE PUT IN COMMON BLOCK, FOR NOW THEY ARE NOT +C USED ANYWHERE ELSE + REAL*8 PS(0:3,NEXTERNAL) + COMMON/ML5_0_PSPOINT/PS +C AGAIN BELOW, MP_PS IS THE FIXED (POSSIBLY IMPROVED) MP PS POINT +C AND MP_P IS THE ONE WHICH CAN BE MODIFIED (I.E. ROTATED ETC.) +C FOR STABILITY PURPOSE +C EVEN THOUGH THEY ARE PUT IN COMMON BLOCK, FOR NOW THEY ARE NOT +C USED ANYWHERE ELSE THAN HERE AND SET_MP_PS() + REAL*16 MP_PS(0:3,NEXTERNAL),MP_P(0:3,NEXTERNAL) + COMMON/ML5_0_MP_PSPOINT/MP_PS,MP_P + + REAL*8 LSCALE + INTEGER CTMODE + COMMON/ML5_0_CT/LSCALE,CTMODE + + LOGICAL GOODHEL(NCOMB) + LOGICAL GOODAMP(NLOOPAMPS,NCOMB) + COMMON/ML5_0_FILTERS/GOODAMP,GOODHEL + + INTEGER HELPICKED + DATA HELPICKED/-1/ + COMMON/ML5_0_HELCHOICE/HELPICKED + INTEGER USERHEL + DATA USERHEL/-1/ + COMMON/ML5_0_USERCHOICE/USERHEL + + COMPLEX*16 AMP(NBORNAMPS,NCOMB) + COMMON/ML5_0_AMPS/AMP + TYPE(ALOHA) W(NWAVEFUNCS,NCOMB) + INTEGER VALIDH + COMMON/ML5_0_WFCTS/W + COMMON/ML5_0_VALIDH/VALIDH + + COMPLEX*16 AMPL(3,NLOOPAMPS) + LOGICAL S(NLOOPAMPS) + COMMON/ML5_0_AMPL/AMPL,S + + INTEGER CF_D(NLOOPAMPS,NBORNAMPS) + INTEGER CF_N(NLOOPAMPS,NBORNAMPS) + COMMON/ML5_0_CF/CF_D,CF_N + + INTEGER HELC(NEXTERNAL,NCOMB) + COMMON/ML5_0_HELCONFIGS/HELC + + REAL*8 PREC,USER_STAB_PREC + DATA USER_STAB_PREC/-1.0D0/ + COMMON/ML5_0_USER_STAB_PREC/USER_STAB_PREC + +C Return codes H,T,U correspond to the hundreds, tens and units +C building returncode, i.e. +C RETURNCODE=100*RET_CODE_H+10*RET_CODE_T+RET_CODE_U + + INTEGER RET_CODE_H,RET_CODE_T,RET_CODE_U + REAL*8 ACCURACY(0:NSQUAREDSO) + DATA (ACCURACY(I),I=0,NSQUAREDSO)/NSQUAREDSOP1*1.0D0/ + DATA RET_CODE_H,RET_CODE_T,RET_CODE_U/1,1,0/ + COMMON/ML5_0_ACC/ACCURACY,RET_CODE_H,RET_CODE_T,RET_CODE_U + +C Allows to forbid the zero helicity double check, no matter the +C value in MadLoopParams.dat +C This can be accessed with the SET_FORBID_HEL_DOUBLECHECK +C subroutine of MadLoopCommons.dat + LOGICAL FORBID_HEL_DOUBLECHECK + COMMON/FORBID_HEL_DOUBLECHECK/FORBID_HEL_DOUBLECHECK + + LOGICAL MP_DONE_ONCE + DATA MP_DONE_ONCE/.FALSE./ + COMMON/ML5_0_MP_DONE_ONCE/MP_DONE_ONCE + + CHARACTER(512) MLPATH + COMMON/MLPATH/MLPATH + + LOGICAL ML_INIT + COMMON/ML_INIT/ML_INIT + +C This variable controls the *local* initialization of this +C particular SubProcess. +C For example, the reading of the filters must be done +C independently by each SubProcess. + LOGICAL LOCAL_ML_INIT + DATA LOCAL_ML_INIT/.TRUE./ + +C Variables related to turning off the Lorentz rotation test when +C spin-2 particles are external + LOGICAL WARNED_LORENTZ_STAB_TEST_OFF + DATA WARNED_LORENTZ_STAB_TEST_OFF/.FALSE./ + INTEGER NROTATIONS_DP_BU,NROTATIONS_QP_BU + +C This array specify potential special requirements on the +C helicities to +C consider. POLARIZATIONS(0,0) is -1 if there is not such +C requirement. + INTEGER POLARIZATIONS(0:NEXTERNAL,0:5) + COMMON/ML5_0_BEAM_POL/POLARIZATIONS + +C ---------- +C BEGIN CODE +C ---------- + + IF(ML_INIT) THEN + CALL PRINT_MADLOOP_BANNER() + TMP = 'auto' + CALL SETMADLOOPPATH(TMP) + CALL JOINPATH(MLPATH,PARAMFNAME,PARAMFN) + CALL MADLOOPPARAMREADER(PARAMFN,.TRUE.) + IF (FORBID_HEL_DOUBLECHECK) THEN + DOUBLECHECKHELICITYFILTER = .FALSE. + ENDIF + ML_INIT = .FALSE. +C For now only CutTools is interfaced in the default mode. +C Samurai could follow. + DO I=1,SIZE(MLREDUCTIONLIB) + IF (MLREDUCTIONLIB(I).EQ.1) THEN + FOUND_VALID_REDUCTION_METHOD = .TRUE. + ENDIF + ENDDO + IF (.NOT.FOUND_VALID_REDUCTION_METHOD) THEN + WRITE(*,*) 'ERROR:: For now, only CutTools is interfaced to' + $ //' MadLoop in the non-optimized output.' + WRITE(*,*) 'ERROR:: Make sure to include 1 in the parameter' + $ //' MLReductionLib of the card MadLoopParams.dat' + STOP 1 + ENDIF + ENDIF + IF (LOCAL_ML_INIT) THEN +C Setup the file paths + CALL JOINPATH(MLPATH,PARAMFNAME,PARAMFN) + CALL JOINPATH(MLPATH,PROC_PREFIX,TMP) + CALL JOINPATH(TMP,HELCONFIGFNAME,HELCONFIGFN) + CALL JOINPATH(TMP,LOOPFILTERFNAME,LOOPFILTERFN) + CALL JOINPATH(TMP,COLORNUMFNAME,COLORNUMFN) + CALL JOINPATH(TMP,COLORDENOMFNAME,COLORDENOMFN) + CALL JOINPATH(TMP,HELFILTERFNAME,HELFILTERFN) + +C Make sure that the loop filter is disabled when there is +C spin-2 particles for 2>1 or 1>2 processes + IF(MAX_SPIN_EXTERNAL_PARTICLE.GT.3.AND.(NEXTERNAL.LE.3.AND.HELI + $CITYFILTERLEVEL.NE.0)) THEN + WRITE(*,*) '##INFO: Helicity filter deactivated for 2>1' + $ //' processes involving spin 2 particles.' + HELICITYFILTERLEVEL = 0 +C We write a dummy filter for structural reasons here + OPEN(1, FILE=HELFILTERFN, ERR=6116, STATUS='NEW' + $ ,ACTION='WRITE') + DO I=1,NCOMB + WRITE(1,*) 'T' + ENDDO + 6116 CONTINUE + CLOSE(1) + ENDIF + + OPEN(1, FILE=COLORNUMFN, ERR=104, STATUS='OLD', + $ ACTION='READ') + DO I=1,NLOOPAMPS + READ(1,*,END=105) (CF_N(I,J),J=1,NBORNAMPS) + ENDDO + GOTO 105 + 104 CONTINUE + STOP 'Color factors could not be initialized from file' + $ //' ML5_0_ColorNumFactors.dat. File not found' + 105 CONTINUE + CLOSE(1) + OPEN(1, FILE=COLORDENOMFN, ERR=106, STATUS='OLD', + $ ACTION='READ') + DO I=1,NLOOPAMPS + READ(1,*,END=107) (CF_D(I,J),J=1,NBORNAMPS) + ENDDO + GOTO 107 + 106 CONTINUE + STOP 'Color factors could not be initialized from file' + $ //' ML5_0_ColorDenomFactors.dat. File not found' + 107 CONTINUE + CLOSE(1) + OPEN(1, FILE=HELCONFIGFN, ERR=108, STATUS='OLD', + $ ACTION='READ') + DO H=1,NCOMB + READ(1,*,END=109) (HELC(I,H),I=1,NEXTERNAL) + ENDDO + GOTO 109 + 108 CONTINUE + STOP 'Color helictiy configurations could not be initialized' + $ //' from file ML5_0_HelConfigs.dat. File not found' + 109 CONTINUE + CLOSE(1) + IF(BOOTANDSTOP) THEN + WRITE(*,*) '##Stopped by user request.' + STOP + ENDIF + LOCAL_ML_INIT = .FALSE. + ENDIF + +C Make sure that lorentz rotation tests are not used if there is +C external loop wavefunction of spin 2 and that one specific +C helicity is asked + NROTATIONS_DP_BU = NROTATIONS_DP + NROTATIONS_QP_BU = NROTATIONS_QP + IF(MAX_SPIN_EXTERNAL_PARTICLE.GT.3.AND.USERHEL.NE.-1) THEN + IF(.NOT.WARNED_LORENTZ_STAB_TEST_OFF) THEN + WRITE(*,*) '##WARNING: Evaluation of a specific helicity was' + $ //' asked for this PS point, and there is a spin-2 (or' + $ //' higher) particle in the external states.' + WRITE(*,*) '##WARNING: As a result, MadLoop disabled the' + $ //' Lorentz rotation test for this phase-space point only.' + WRITE(*,*) '##WARNING: Further warning of that type' + $ //' suppressed.' + WARNED_LORENTZ_STAB_TEST_OFF = .FALSE. + ENDIF + NROTATIONS_QP=0 + NROTATIONS_DP=0 + ENDIF + + IF(NTRY.EQ.0) THEN + CALL ML5_0_SET_N_EVALS(N_DP_EVAL,N_QP_EVAL) + HELDOUBLECHECKED=(.NOT.DOUBLECHECKHELICITYFILTER) + $ .OR.(HELICITYFILTERLEVEL.EQ.0) + DO J=1,NCOMB + DO I=1,NCTAMPS + GOODAMP(I,J)=.TRUE. + ENDDO + ENDDO + OPEN(1, FILE=LOOPFILTERFN, ERR=100, STATUS='OLD', + $ ACTION='READ') + DO J=1,NCOMB + READ(1,*,END=101) (GOODAMP(I,J),I=NCTAMPS+1,NLOOPAMPS) + ENDDO + GOTO 101 + 100 CONTINUE + FOUNDLOOPFILTER=.FALSE. + DO J=1,NCOMB + DO I=NCTAMPS+1,NLOOPAMPS + GOODAMP(I,J)=(.NOT.USELOOPFILTER) + ENDDO + ENDDO + 101 CONTINUE + CLOSE(1) + IF (HELICITYFILTERLEVEL.EQ.0) THEN + FOUNDHELFILTER=.TRUE. + DO J=1,NCOMB + GOODHEL(J)=.TRUE. + ENDDO + GOTO 122 + ENDIF + OPEN(1, FILE=HELFILTERFN, ERR=102, STATUS='OLD', + $ ACTION='READ') + READ(1,*,END=103) (GOODHEL(I),I=1,NCOMB) + GOTO 103 + 102 CONTINUE + FOUNDHELFILTER=.FALSE. + DO J=1,NCOMB + GOODHEL(J)=.TRUE. + ENDDO + 103 CONTINUE + CLOSE(1) + 122 CONTINUE + ENDIF + + MP_DONE=.FALSE. + MP_DONE_ONCE=.FALSE. + MP_PS_SET=.FALSE. + STAB_INDEX=0 + DOING_QP_EVALS=.FALSE. + EVAL_DONE(1)=.TRUE. + DO I=2,MAXSTABILITYLENGTH + EVAL_DONE(I)=.FALSE. + ENDDO + +C Compute the born, for a specific helicity if asked so. + CALL ML5_0_SMATRIXHEL(P_USER,USERHEL,FLAVOR,ANS(0)) + + + IF (USER_STAB_PREC.GT.0.0D0) THEN + MLSTABTHRES_BU=MLSTABTHRES + MLSTABTHRES=USER_STAB_PREC +C In the initialization, I cannot perform stability test and +C therefore guarantee any precision + CTMODEINIT_BU=CTMODEINIT +C So either one choses quad precision directly +C CTMODEINIT=4 +C Or, because this is very slow, we keep the orignal value. The +C accuracy returned is -1 and tells the MC that he should not +C trust the evaluation for checks. + CTMODEINIT=CTMODEINIT_BU + ENDIF + + IF(.NOT.BYPASS_CHECK) THEN + NTRY=NTRY+1 + ENDIF + + IF(DONEHELDOUBLECHECK.AND.(.NOT.HELDOUBLECHECKED)) THEN + HELDOUBLECHECKED=.TRUE. + DONEHELDOUBLECHECK=.FALSE. + ENDIF + + CHECKPHASE=(NTRY.LE.CHECKCYCLE).AND.(((.NOT.FOUNDLOOPFILTER) + $ .AND.USELOOPFILTER).OR.(.NOT.FOUNDHELFILTER)) + + IF (WRITEOUTFILTERS) THEN + IF ((.NOT. CHECKPHASE).AND.(.NOT.FOUNDHELFILTER)) THEN + OPEN(1, FILE=HELFILTERFN, ERR=110, STATUS='NEW' + $ ,ACTION='WRITE') + WRITE(1,*) (GOODHEL(I),I=1,NCOMB) + 110 CONTINUE + CLOSE(1) + FOUNDHELFILTER=.TRUE. + ENDIF + + IF ((.NOT. CHECKPHASE).AND.(.NOT.FOUNDLOOPFILTER) + $ .AND.USELOOPFILTER) THEN + OPEN(1, FILE=LOOPFILTERFN, ERR=111, STATUS='NEW' + $ ,ACTION='WRITE') + DO J=1,NCOMB + WRITE(1,*) (GOODAMP(I,J),I=NCTAMPS+1,NLOOPAMPS) + ENDDO + 111 CONTINUE + CLOSE(1) + FOUNDLOOPFILTER=.TRUE. + ENDIF + ENDIF + + IF (BYPASS_CHECK) THEN + OLD_CHECKPHASE = CHECKPHASE + OLD_HELDOUBLECHECKED = HELDOUBLECHECKED + CHECKPHASE = .FALSE. + HELDOUBLECHECKED = .TRUE. + DO I=1,NCOMB + OLD_GOODHEL(I)=GOODHEL(I) + GOODHEL(I) = .TRUE. + ENDDO + DO I=1,NCOMB + DO J=1,NLOOPAMPS + OLD_GOODAMP(J,I)=GOODAMP(J,I) + GOODAMP(J,I) = .TRUE. + ENDDO + ENDDO + ENDIF + + IF(CHECKPHASE.OR.(.NOT.HELDOUBLECHECKED)) THEN + HELPICKED=1 + CTMODE=CTMODEINIT + ELSE + IF (USERHEL.NE.-1) THEN + IF(.NOT.GOODHEL(USERHEL)) THEN + ANS(1)=0.0D0 + ANS(2)=0.0D0 + ANS(3)=0.0D0 + GOTO 9999 + ENDIF + ENDIF + HELPICKED=USERHEL + IF (CTMODERUN.GT.-1) THEN + CTMODE=CTMODERUN + ELSE + CTMODE=1 + ENDIF + ENDIF + + DO I=1,NEXTERNAL + DO J=0,3 + PS(J,I)=P_USER(J,I) + ENDDO + ENDDO + + IF (IMPROVEPSPOINT.GE.0) THEN +C Make the input PS more precise (exact onshell and +C energy-momentum conservation) + CALL ML5_0_IMPROVE_PS_POINT_PRECISION(PS) + ENDIF + + DO I=1,NEXTERNAL + DO J=0,3 + P(J,I)=PS(J,I) + ENDDO + ENDDO + + DO K=1, 3 + BUFFR(K)=0.0D0 + DO I=1,NLOOPAMPS + AMPL(K,I)=(0.0D0,0.0D0) + ENDDO + ENDDO + + LSCALE=DSQRT(ABS((P(0,1)+P(0,2))**2-(P(1,1)+P(1,2))**2-(P(2,1) + $ +P(2,2))**2-(P(3,1)+P(3,2))**2)) + +C We chose to use the born evaluation for the reference + CALL ML5_0_SMATRIX(P,FLAVOR,REF) + + 200 CONTINUE + + IF (CTMODE.EQ.0.OR.CTMODE.GE.4) THEN + CALL MP_UPDATE_AS_PARAM() + ENDIF + + IF (.NOT.MP_PS_SET.AND.(CTMODE.EQ.0.OR.CTMODE.GE.4)) THEN + CALL ML5_0_SET_MP_PS(P_USER) + MP_PS_SET = .TRUE. + ENDIF + + DO K=1,3 + ANS(K)=0.0D0 + ENDDO + + VALIDH=-1 + DO H=1,NCOMB + IF ((HELPICKED.EQ.H).OR.((HELPICKED.EQ.-1) + $ .AND.(CHECKPHASE.OR.(.NOT.HELDOUBLECHECKED).OR.GOODHEL(H)))) + $ THEN + +C Handle the possible requirement of specific polarizations + IF ((.NOT.CHECKPHASE) + $ .AND.HELDOUBLECHECKED.AND.POLARIZATIONS(0,0) + $ .EQ.0.AND.(.NOT.ML5_0_IS_HEL_SELECTED(H))) THEN + CYCLE + ENDIF + + IF (VALIDH.EQ.-1) VALIDH=H + DO I=1,NEXTERNAL + NHEL(I)=HELC(I,H) + ENDDO +C Check if we are in multiple precision and compute wfs and +C amps accordingly if needed + IF (CTMODE.GE.4) THEN +C Force that only current helicity is used in the routine +C below +C This should always be done, even if MP_DONE is True +C because the AMPL of the R2 MUST be recomputed for loop +C induced. +C (because they are not saved for each hel configuration) +C (This is not optimal unlike what is done int the loop +C optimized output) + HELPICKED_BU = HELPICKED + HELPICKED = H + CALL ML5_0_MP_BORN_AMPS_AND_WFS(MP_P) + HELPICKED = HELPICKED_BU + GOTO 300 + ENDIF + CALL VXXXXX(P(0,1),ZERO,NHEL(1),-1,W(1,H)) + CALL VXXXXX(P(0,2),ZERO,NHEL(2),-1,W(2,H)) + CALL OXXXXX(P(0,3),MDL_MT,NHEL(3),+1, FLAVOR(3),W(3,H)) + CALL IXXXXX(P(0,4),MDL_MT,NHEL(4),-1, FLAVOR(4),W(4,H)) + CALL VVV1P0_1(W(1,H),W(2,H),GC_4,ZERO,ZERO,W(5,H)) +C Amplitude(s) for born diagram with ID 1 + CALL FFV1_0(W(4,H),W(3,H),W(5,H),GC_5,AMP(1,H)) + CALL FFV1_1(W(3,H),W(1,H),GC_5,MDL_MT,MDL_WT,W(6,H)) +C Amplitude(s) for born diagram with ID 2 + CALL FFV1_0(W(4,H),W(6,H),W(2,H),GC_5,AMP(2,H)) + CALL FFV1_2(W(4,H),W(1,H),GC_5,MDL_MT,MDL_WT,W(7,H)) +C Amplitude(s) for born diagram with ID 3 + CALL FFV1_0(W(7,H),W(3,H),W(2,H),GC_5,AMP(3,H)) + CALL FFV1P0_3(W(4,H),W(3,H),GC_5,ZERO,ZERO,W(8,H)) +C Counter-term amplitude(s) for loop diagram number 4 + CALL R2_GG_1_R2_GG_2_0(W(5,H),W(8,H),R2_GGG_1,R2_GGG_2 + $ ,AMPL(1,1)) +C Counter-term amplitude(s) for loop diagram number 5 + CALL FFV1_0(W(4,H),W(3,H),W(5,H),R2_GQQ,AMPL(1,2)) + CALL FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQB_1EPS,AMPL(2,3)) + CALL FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQB_1EPS,AMPL(2,4)) + CALL FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQB_1EPS,AMPL(2,5)) + CALL FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQB_1EPS,AMPL(2,6)) + CALL FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQB_1EPS,AMPL(2,7)) + CALL FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQB_1EPS,AMPL(2,8)) + CALL FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQG_1EPS,AMPL(2,9)) + CALL FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQB,AMPL(1,10)) + CALL FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQT,AMPL(1,11)) + CALL FFV1_2(W(4,H),W(2,H),GC_5,MDL_MT,MDL_WT,W(9,H)) +C Counter-term amplitude(s) for loop diagram number 7 + CALL R2_QQ_1_R2_QQ_2_0(W(9,H),W(6,H),R2_QQQ,R2_QQT,AMPL(1,12) + $ ) + CALL R2_QQ_2_0(W(9,H),W(6,H),UV_TMASS_1EPS,AMPL(2,13)) + CALL R2_QQ_2_0(W(9,H),W(6,H),UV_TMASS,AMPL(1,14)) +C Counter-term amplitude(s) for loop diagram number 8 + CALL FFV1_0(W(4,H),W(6,H),W(2,H),R2_GQQ,AMPL(1,15)) + CALL FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQB_1EPS,AMPL(2,16)) + CALL FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQB_1EPS,AMPL(2,17)) + CALL FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQB_1EPS,AMPL(2,18)) + CALL FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQB_1EPS,AMPL(2,19)) + CALL FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQB_1EPS,AMPL(2,20)) + CALL FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQB_1EPS,AMPL(2,21)) + CALL FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQG_1EPS,AMPL(2,22)) + CALL FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQB,AMPL(1,23)) + CALL FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQT,AMPL(1,24)) + CALL FFV1_1(W(3,H),W(2,H),GC_5,MDL_MT,MDL_WT,W(10,H)) +C Counter-term amplitude(s) for loop diagram number 10 + CALL R2_QQ_1_R2_QQ_2_0(W(7,H),W(10,H),R2_QQQ,R2_QQT,AMPL(1 + $ ,25)) + CALL R2_QQ_2_0(W(7,H),W(10,H),UV_TMASS_1EPS,AMPL(2,26)) + CALL R2_QQ_2_0(W(7,H),W(10,H),UV_TMASS,AMPL(1,27)) +C Counter-term amplitude(s) for loop diagram number 11 + CALL FFV1_0(W(7,H),W(3,H),W(2,H),R2_GQQ,AMPL(1,28)) + CALL FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQB_1EPS,AMPL(2,29)) + CALL FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQB_1EPS,AMPL(2,30)) + CALL FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQB_1EPS,AMPL(2,31)) + CALL FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQB_1EPS,AMPL(2,32)) + CALL FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQB_1EPS,AMPL(2,33)) + CALL FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQB_1EPS,AMPL(2,34)) + CALL FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQG_1EPS,AMPL(2,35)) + CALL FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQB,AMPL(1,36)) + CALL FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQT,AMPL(1,37)) +C Counter-term amplitude(s) for loop diagram number 13 + CALL FFV1_0(W(4,H),W(10,H),W(1,H),R2_GQQ,AMPL(1,38)) + CALL FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQB_1EPS,AMPL(2,39)) + CALL FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQB_1EPS,AMPL(2,40)) + CALL FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQB_1EPS,AMPL(2,41)) + CALL FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQB_1EPS,AMPL(2,42)) + CALL FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQB_1EPS,AMPL(2,43)) + CALL FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQB_1EPS,AMPL(2,44)) + CALL FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQG_1EPS,AMPL(2,45)) + CALL FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQB,AMPL(1,46)) + CALL FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQT,AMPL(1,47)) +C Counter-term amplitude(s) for loop diagram number 14 + CALL FFV1_0(W(9,H),W(3,H),W(1,H),R2_GQQ,AMPL(1,48)) + CALL FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQB_1EPS,AMPL(2,49)) + CALL FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQB_1EPS,AMPL(2,50)) + CALL FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQB_1EPS,AMPL(2,51)) + CALL FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQB_1EPS,AMPL(2,52)) + CALL FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQB_1EPS,AMPL(2,53)) + CALL FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQB_1EPS,AMPL(2,54)) + CALL FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQG_1EPS,AMPL(2,55)) + CALL FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQB,AMPL(1,56)) + CALL FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQT,AMPL(1,57)) +C Counter-term amplitude(s) for loop diagram number 17 + CALL VVV1_0(W(1,H),W(2,H),W(8,H),R2_3GG,AMPL(1,58)) + CALL VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GB_1EPS,AMPL(2,59)) + CALL VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GB_1EPS,AMPL(2,60)) + CALL VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GB_1EPS,AMPL(2,61)) + CALL VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GB_1EPS,AMPL(2,62)) + CALL VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GB_1EPS,AMPL(2,63)) + CALL VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GB_1EPS,AMPL(2,64)) + CALL VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GG_1EPS,AMPL(2,65)) + CALL VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GB,AMPL(1,66)) + CALL VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GT,AMPL(1,67)) +C Counter-term amplitude(s) for loop diagram number 31 + CALL R2_GG_1_0(W(5,H),W(8,H),R2_GGQ,AMPL(1,68)) + CALL R2_GG_1_0(W(5,H),W(8,H),R2_GGQ,AMPL(1,69)) + CALL R2_GG_1_0(W(5,H),W(8,H),R2_GGQ,AMPL(1,70)) + CALL R2_GG_1_0(W(5,H),W(8,H),R2_GGQ,AMPL(1,71)) +C Counter-term amplitude(s) for loop diagram number 32 + CALL VVV1_0(W(1,H),W(2,H),W(8,H),R2_3GQ,AMPL(1,72)) + CALL VVV1_0(W(1,H),W(2,H),W(8,H),R2_3GQ,AMPL(1,73)) + CALL VVV1_0(W(1,H),W(2,H),W(8,H),R2_3GQ,AMPL(1,74)) + CALL VVV1_0(W(1,H),W(2,H),W(8,H),R2_3GQ,AMPL(1,75)) +C Counter-term amplitude(s) for loop diagram number 34 + CALL R2_GG_1_R2_GG_3_0(W(5,H),W(8,H),R2_GGQ,R2_GGB,AMPL(1,76) + $ ) +C Counter-term amplitude(s) for loop diagram number 35 + CALL VVV1_0(W(1,H),W(2,H),W(8,H),R2_3GQ,AMPL(1,77)) +C Counter-term amplitude(s) for loop diagram number 37 + CALL R2_GG_1_R2_GG_3_0(W(5,H),W(8,H),R2_GGQ,R2_GGT,AMPL(1,78) + $ ) +C Counter-term amplitude(s) for loop diagram number 38 + CALL VVV1_0(W(1,H),W(2,H),W(8,H),R2_3GQ,AMPL(1,79)) +C Amplitude(s) for UVCT diagram with ID 40 + CALL FFV1_0(W(4,H),W(3,H),W(5,H),GC_5,AMPL(2,80)) + AMPL(2,80)=AMPL(2,80)*(4.0D0*UVWFCT_G_1_1EPS+2.0D0 + $ *UVWFCT_B_0_1EPS) +C Amplitude(s) for UVCT diagram with ID 41 + CALL FFV1_0(W(4,H),W(3,H),W(5,H),GC_5,AMPL(1,81)) + AMPL(1,81)=AMPL(1,81)*(2.0D0*UVWFCT_G_1+2.0D0*UVWFCT_G_2 + $ +2.0D0*UVWFCT_T_0) +C Amplitude(s) for UVCT diagram with ID 42 + CALL FFV1_0(W(4,H),W(6,H),W(2,H),GC_5,AMPL(2,82)) + AMPL(2,82)=AMPL(2,82)*(4.0D0*UVWFCT_G_1_1EPS+2.0D0 + $ *UVWFCT_B_0_1EPS) +C Amplitude(s) for UVCT diagram with ID 43 + CALL FFV1_0(W(4,H),W(6,H),W(2,H),GC_5,AMPL(1,83)) + AMPL(1,83)=AMPL(1,83)*(2.0D0*UVWFCT_G_1+2.0D0*UVWFCT_G_2 + $ +2.0D0*UVWFCT_T_0) +C Amplitude(s) for UVCT diagram with ID 44 + CALL FFV1_0(W(7,H),W(3,H),W(2,H),GC_5,AMPL(2,84)) + AMPL(2,84)=AMPL(2,84)*(4.0D0*UVWFCT_G_1_1EPS+2.0D0 + $ *UVWFCT_B_0_1EPS) +C Amplitude(s) for UVCT diagram with ID 45 + CALL FFV1_0(W(7,H),W(3,H),W(2,H),GC_5,AMPL(1,85)) + AMPL(1,85)=AMPL(1,85)*(2.0D0*UVWFCT_G_1+2.0D0*UVWFCT_G_2 + $ +2.0D0*UVWFCT_T_0) + 300 CONTINUE + + + + DO I=1,NCTAMPS + DO J=1,NBORNAMPS + CFTOT=DCMPLX(CF_N(I,J)/DBLE(ABS(CF_D(I,J))),0.0D0) + IF(CF_D(I,J).LT.0) CFTOT=CFTOT*IMAG1 + DO K=1,3 + ANS(K)=ANS(K)+2.0D0*DBLE(CFTOT*AMPL(K,I)*DCONJG(AMP(J + $ ,H))) + ENDDO + ENDDO + ENDDO + ENDIF + ENDDO + +C WHEN CTMODE IS >=4, then the MP computation of wfs and amps is +C automatically done. + IF (CTMODE.GE.4) THEN + MP_DONE = .TRUE. + ENDIF + + IF(SKIPLOOPEVAL) THEN + GOTO 1226 + ENDIF + +C Loop amplitude for loop diagram with ID 4 + CALL ML5_0_LOOP_2_2(1,5,8,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) + $ ,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4,GC_4 + $ ,MP__GC_4,2,2,1,86,AMPL(1,86),S(86)) +C Loop amplitude for loop diagram with ID 5 + CALL ML5_0_LOOP_3_3(2,3,4,5,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT + $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),DCMPLX(ZERO) + $ ,CMPLX(MP__ZERO,KIND=16),GC_5,MP__GC_5,GC_5,MP__GC_5,GC_4 + $ ,MP__GC_4,2,1,1,87,AMPL(1,87),S(87)) +C Loop amplitude for loop diagram with ID 6 + CALL ML5_0_LOOP_3_3(3,3,4,5,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) + $ ,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16),DCMPLX(MDL_MT) + $ ,CMPLX(MP__MDL_MT,KIND=16),GC_5,MP__GC_5,GC_5,MP__GC_5,GC_5 + $ ,MP__GC_5,2,1,1,88,AMPL(1,88),S(88)) +C Loop amplitude for loop diagram with ID 7 + CALL ML5_0_LOOP_2_2(4,6,9,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) + $ ,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16),GC_5,MP__GC_5,GC_5 + $ ,MP__GC_5,1,1,1,89,AMPL(1,89),S(89)) +C Loop amplitude for loop diagram with ID 8 + CALL ML5_0_LOOP_3_3(5,2,4,6,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) + $ ,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16),DCMPLX(ZERO) + $ ,CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4,GC_5,MP__GC_5,GC_5 + $ ,MP__GC_5,2,1,1,90,AMPL(1,90),S(90)) +C Loop amplitude for loop diagram with ID 9 + CALL ML5_0_LOOP_3_3(6,2,4,6,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT + $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),DCMPLX(MDL_MT) + $ ,CMPLX(MP__MDL_MT,KIND=16),GC_5,MP__GC_5,GC_5,MP__GC_5,GC_5 + $ ,MP__GC_5,2,1,1,91,AMPL(1,91),S(91)) +C Loop amplitude for loop diagram with ID 10 + CALL ML5_0_LOOP_2_2(4,10,7,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) + $ ,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16),GC_5,MP__GC_5,GC_5 + $ ,MP__GC_5,1,1,1,92,AMPL(1,92),S(92)) +C Loop amplitude for loop diagram with ID 11 + CALL ML5_0_LOOP_3_3(7,2,3,7,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) + $ ,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16),DCMPLX(ZERO) + $ ,CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4,GC_5,MP__GC_5,GC_5 + $ ,MP__GC_5,2,1,1,93,AMPL(1,93),S(93)) +C Loop amplitude for loop diagram with ID 12 + CALL ML5_0_LOOP_3_3(8,2,3,7,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT + $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),DCMPLX(MDL_MT) + $ ,CMPLX(MP__MDL_MT,KIND=16),GC_5,MP__GC_5,GC_5,MP__GC_5,GC_5 + $ ,MP__GC_5,2,1,1,94,AMPL(1,94),S(94)) +C Loop amplitude for loop diagram with ID 13 + CALL ML5_0_LOOP_3_3(5,1,4,10,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) + $ ,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16),DCMPLX(ZERO) + $ ,CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4,GC_5,MP__GC_5,GC_5 + $ ,MP__GC_5,2,1,1,95,AMPL(1,95),S(95)) +C Loop amplitude for loop diagram with ID 14 + CALL ML5_0_LOOP_3_3(7,1,3,9,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) + $ ,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16),DCMPLX(ZERO) + $ ,CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4,GC_5,MP__GC_5,GC_5 + $ ,MP__GC_5,2,1,1,96,AMPL(1,96),S(96)) +C Loop amplitude for loop diagram with ID 15 + CALL ML5_0_LOOP_4_4(9,1,2,4,3,DCMPLX(ZERO),CMPLX(MP__ZERO + $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),DCMPLX(MDL_MT) + $ ,CMPLX(MP__MDL_MT,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) + $ ,GC_4,MP__GC_4,GC_4,MP__GC_4,GC_5,MP__GC_5,GC_5,MP__GC_5,3,1,1 + $ ,97,AMPL(1,97),S(97)) +C Loop amplitude for loop diagram with ID 16 + CALL ML5_0_LOOP_4_4(10,1,2,3,4,DCMPLX(ZERO),CMPLX(MP__ZERO + $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),DCMPLX(MDL_MT) + $ ,CMPLX(MP__MDL_MT,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) + $ ,GC_4,MP__GC_4,GC_4,MP__GC_4,GC_5,MP__GC_5,GC_5,MP__GC_5,3,1,1 + $ ,98,AMPL(1,98),S(98)) +C Loop amplitude for loop diagram with ID 17 + CALL ML5_0_LOOP_3_3(11,1,2,8,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) + $ ,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),DCMPLX(ZERO) + $ ,CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4,GC_4,MP__GC_4,GC_4 + $ ,MP__GC_4,3,1,1,99,AMPL(1,99),S(99)) +C Loop amplitude for loop diagram with ID 18 + CALL ML5_0_LOOP_2_3_2(12,1,2,1,8,2,DCMPLX(ZERO),CMPLX(MP__ZERO + $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4 + $ ,GC_6,MP__GC_6,1,2,1,100,AMPL(1,100),S(100)) + CALL ML5_0_LOOP_2_3_2(13,1,2,1,8,2,DCMPLX(ZERO),CMPLX(MP__ZERO + $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4 + $ ,GC_6,MP__GC_6,1,2,1,101,AMPL(1,101),S(101)) + CALL ML5_0_LOOP_2_3_2(14,1,2,1,8,2,DCMPLX(ZERO),CMPLX(MP__ZERO + $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4 + $ ,GC_6,MP__GC_6,1,2,1,102,AMPL(1,102),S(102)) +C Loop amplitude for loop diagram with ID 19 + CALL ML5_0_LOOP_4_4(15,1,3,2,4,DCMPLX(ZERO),CMPLX(MP__ZERO + $ ,KIND=16),DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16) + $ ,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16),DCMPLX(ZERO) + $ ,CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4,GC_5,MP__GC_5,GC_5 + $ ,MP__GC_5,GC_5,MP__GC_5,3,1,1,103,AMPL(1,103),S(103)) +C Loop amplitude for loop diagram with ID 20 + CALL ML5_0_LOOP_3_3(6,1,4,10,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT + $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),DCMPLX(MDL_MT) + $ ,CMPLX(MP__MDL_MT,KIND=16),GC_5,MP__GC_5,GC_5,MP__GC_5,GC_5 + $ ,MP__GC_5,2,1,1,104,AMPL(1,104),S(104)) +C Loop amplitude for loop diagram with ID 21 + CALL ML5_0_LOOP_3_3(8,1,3,9,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT + $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),DCMPLX(MDL_MT) + $ ,CMPLX(MP__MDL_MT,KIND=16),GC_5,MP__GC_5,GC_5,MP__GC_5,GC_5 + $ ,MP__GC_5,2,1,1,105,AMPL(1,105),S(105)) +C Loop amplitude for loop diagram with ID 22 + CALL ML5_0_LOOP_2_3_2(12,1,2,2,8,1,DCMPLX(ZERO),CMPLX(MP__ZERO + $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4 + $ ,GC_6,MP__GC_6,1,2,1,106,AMPL(1,106),S(106)) + CALL ML5_0_LOOP_2_3_2(13,1,2,2,8,1,DCMPLX(ZERO),CMPLX(MP__ZERO + $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4 + $ ,GC_6,MP__GC_6,1,2,1,107,AMPL(1,107),S(107)) + CALL ML5_0_LOOP_2_3_2(14,1,2,2,8,1,DCMPLX(ZERO),CMPLX(MP__ZERO + $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4 + $ ,GC_6,MP__GC_6,1,2,1,108,AMPL(1,108),S(108)) +C Loop amplitude for loop diagram with ID 23 + CALL ML5_0_LOOP_4_4(16,1,3,2,4,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT + $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),DCMPLX(ZERO) + $ ,CMPLX(MP__ZERO,KIND=16),DCMPLX(MDL_MT),CMPLX(MP__MDL_MT + $ ,KIND=16),GC_5,MP__GC_5,GC_5,MP__GC_5,GC_4,MP__GC_4,GC_5 + $ ,MP__GC_5,3,1,1,109,AMPL(1,109),S(109)) +C Loop amplitude for loop diagram with ID 24 + CALL ML5_0_LOOP_4_4(17,1,2,4,3,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT + $ ,KIND=16),DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16),DCMPLX(ZERO) + $ ,CMPLX(MP__ZERO,KIND=16),DCMPLX(MDL_MT),CMPLX(MP__MDL_MT + $ ,KIND=16),GC_5,MP__GC_5,GC_5,MP__GC_5,GC_5,MP__GC_5,GC_5 + $ ,MP__GC_5,3,1,1,110,AMPL(1,110),S(110)) +C Loop amplitude for loop diagram with ID 25 + CALL ML5_0_LOOP_4_4(18,1,2,3,4,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT + $ ,KIND=16),DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16),DCMPLX(ZERO) + $ ,CMPLX(MP__ZERO,KIND=16),DCMPLX(MDL_MT),CMPLX(MP__MDL_MT + $ ,KIND=16),GC_5,MP__GC_5,GC_5,MP__GC_5,GC_5,MP__GC_5,GC_5 + $ ,MP__GC_5,3,1,1,111,AMPL(1,111),S(111)) +C Loop amplitude for loop diagram with ID 26 + CALL ML5_0_LOOP_2_3_2(19,2,1,2,1,8,DCMPLX(ZERO),CMPLX(MP__ZERO + $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_6,MP__GC_6 + $ ,GC_4,MP__GC_4,1,2,1,112,AMPL(1,112),S(112)) + CALL ML5_0_LOOP_2_3_2(20,2,1,2,1,8,DCMPLX(ZERO),CMPLX(MP__ZERO + $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_6,MP__GC_6 + $ ,GC_4,MP__GC_4,1,2,1,113,AMPL(1,113),S(113)) + CALL ML5_0_LOOP_2_3_2(21,2,1,2,1,8,DCMPLX(ZERO),CMPLX(MP__ZERO + $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_6,MP__GC_6 + $ ,GC_4,MP__GC_4,1,2,1,114,AMPL(1,114),S(114)) +C Loop amplitude for loop diagram with ID 27 + CALL ML5_0_LOOP_3_4_3(22,1,1,2,3,4,2,1,DCMPLX(MDL_MT) + $ ,CMPLX(MP__MDL_MT,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) + $ ,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_5,MP__GC_5,GC_5 + $ ,MP__GC_5,GC_6,MP__GC_6,1,1,1,115,AMPL(1,115),S(115)) + CALL ML5_0_LOOP_3_4_3(23,1,1,2,3,4,2,1,DCMPLX(MDL_MT) + $ ,CMPLX(MP__MDL_MT,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) + $ ,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_5,MP__GC_5,GC_5 + $ ,MP__GC_5,GC_6,MP__GC_6,1,1,1,116,AMPL(1,116),S(116)) + CALL ML5_0_LOOP_3_4_3(24,1,1,2,3,4,2,1,DCMPLX(MDL_MT) + $ ,CMPLX(MP__MDL_MT,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) + $ ,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_5,MP__GC_5,GC_5 + $ ,MP__GC_5,GC_6,MP__GC_6,1,1,1,117,AMPL(1,117),S(117)) +C Loop amplitude for loop diagram with ID 28 + CALL ML5_0_LOOP_2_2(25,5,8,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) + $ ,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4,GC_4 + $ ,MP__GC_4,2,1,1,118,AMPL(1,118),S(118)) +C Loop amplitude for loop diagram with ID 29 + CALL ML5_0_LOOP_3_3(26,1,2,8,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) + $ ,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),DCMPLX(ZERO) + $ ,CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4,GC_4,MP__GC_4,GC_4 + $ ,MP__GC_4,3,1,1,119,AMPL(1,119),S(119)) +C Loop amplitude for loop diagram with ID 30 + CALL ML5_0_LOOP_3_3(27,1,2,8,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) + $ ,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),DCMPLX(ZERO) + $ ,CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4,GC_4,MP__GC_4,GC_4 + $ ,MP__GC_4,3,1,1,120,AMPL(1,120),S(120)) +C Loop amplitude for loop diagram with ID 31 + CALL ML5_0_LOOP_2_2(28,5,8,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) + $ ,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_5,MP__GC_5,GC_5 + $ ,MP__GC_5,2,1,4,121,AMPL(1,121),S(121)) +C Loop amplitude for loop diagram with ID 32 + CALL ML5_0_LOOP_3_3(29,1,2,8,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) + $ ,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),DCMPLX(ZERO) + $ ,CMPLX(MP__ZERO,KIND=16),GC_5,MP__GC_5,GC_5,MP__GC_5,GC_5 + $ ,MP__GC_5,3,1,4,122,AMPL(1,122),S(122)) +C Loop amplitude for loop diagram with ID 33 + CALL ML5_0_LOOP_3_3(30,1,2,8,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) + $ ,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),DCMPLX(ZERO) + $ ,CMPLX(MP__ZERO,KIND=16),GC_5,MP__GC_5,GC_5,MP__GC_5,GC_5 + $ ,MP__GC_5,3,1,4,123,AMPL(1,123),S(123)) +C Loop amplitude for loop diagram with ID 34 + CALL ML5_0_LOOP_2_2(28,5,8,DCMPLX(MDL_MB),CMPLX(MP__MDL_MB + $ ,KIND=16),DCMPLX(MDL_MB),CMPLX(MP__MDL_MB,KIND=16),GC_5 + $ ,MP__GC_5,GC_5,MP__GC_5,2,1,1,124,AMPL(1,124),S(124)) +C Loop amplitude for loop diagram with ID 35 + CALL ML5_0_LOOP_3_3(29,1,2,8,DCMPLX(MDL_MB),CMPLX(MP__MDL_MB + $ ,KIND=16),DCMPLX(MDL_MB),CMPLX(MP__MDL_MB,KIND=16) + $ ,DCMPLX(MDL_MB),CMPLX(MP__MDL_MB,KIND=16),GC_5,MP__GC_5,GC_5 + $ ,MP__GC_5,GC_5,MP__GC_5,3,1,1,125,AMPL(1,125),S(125)) +C Loop amplitude for loop diagram with ID 36 + CALL ML5_0_LOOP_3_3(30,1,2,8,DCMPLX(MDL_MB),CMPLX(MP__MDL_MB + $ ,KIND=16),DCMPLX(MDL_MB),CMPLX(MP__MDL_MB,KIND=16) + $ ,DCMPLX(MDL_MB),CMPLX(MP__MDL_MB,KIND=16),GC_5,MP__GC_5,GC_5 + $ ,MP__GC_5,GC_5,MP__GC_5,3,1,1,126,AMPL(1,126),S(126)) +C Loop amplitude for loop diagram with ID 37 + CALL ML5_0_LOOP_2_2(28,5,8,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT + $ ,KIND=16),DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16),GC_5 + $ ,MP__GC_5,GC_5,MP__GC_5,2,1,1,127,AMPL(1,127),S(127)) +C Loop amplitude for loop diagram with ID 38 + CALL ML5_0_LOOP_3_3(29,1,2,8,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT + $ ,KIND=16),DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16) + $ ,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16),GC_5,MP__GC_5,GC_5 + $ ,MP__GC_5,GC_5,MP__GC_5,3,1,1,128,AMPL(1,128),S(128)) +C Loop amplitude for loop diagram with ID 39 + CALL ML5_0_LOOP_3_3(30,1,2,8,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT + $ ,KIND=16),DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16) + $ ,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16),GC_5,MP__GC_5,GC_5 + $ ,MP__GC_5,GC_5,MP__GC_5,3,1,1,129,AMPL(1,129),S(129)) + + DO I=NCTAMPS+1,NLOOPAMPS + ANS(1)=ANS(1)+AMPL(1,I) + ANS(2)=ANS(2)+AMPL(2,I) + ANS(3)=ANS(3)+AMPL(3,I) + IF((CTMODERUN.NE.-1).AND..NOT.CHECKPHASE.AND.(.NOT.S(I))) THEN + WRITE(*,*) '##W03 WARNING Contribution ',I,' is unstable.' + ENDIF + ENDDO + + 1226 CONTINUE + + IF (CHECKPHASE.OR.(.NOT.HELDOUBLECHECKED)) THEN +C Update of NEXTREF, will be used for loop induced only. + NEXTREF = NEXTREF + ANS(1) + ANS(2) + ANS(3) + IF((USERHEL.EQ.-1).OR.(USERHEL.EQ.HELPICKED)) THEN + BUFFR(1)=BUFFR(1)+ANS(1) + BUFFR(2)=BUFFR(2)+ANS(2) + BUFFR(3)=BUFFR(3)+ANS(3) + ENDIF + + IF (CHECKPHASE) THEN +C SET THE HELICITY FILTER + IF(.NOT.FOUNDHELFILTER) THEN + IF(ML5_0_ISZERO(ABS(ANS(1))+ABS(ANS(2))+ABS(ANS(3)),REF + $ /DBLE(NCOMB),-1)) THEN + IF(NTRY.EQ.1) THEN + GOODHEL(HELPICKED)=.FALSE. + ELSEIF(GOODHEL(HELPICKED)) THEN + WRITE(*,*) '##W02A WARNING Inconsistent helicity ' + $ ,HELPICKED + IF(HELINITSTARTOVER) THEN + WRITE(*,*) '##I01 INFO Initialization starting over' + $ //' because of inconsistency in the helicity filter' + $ //' setup.' + NTRY=0 + ENDIF + ENDIF + ELSE + IF(.NOT.GOODHEL(HELPICKED)) THEN + WRITE(*,*) '##W02B WARNING Inconsistent helicity ' + $ ,HELPICKED + IF(HELINITSTARTOVER) THEN + WRITE(*,*) '##I01 INFO Initialization starting over' + $ //' because of inconsistency in the helicity filter' + $ //' setup.' + NTRY=0 + ELSE + GOODHEL(HELPICKED)=.TRUE. + ENDIF + ENDIF + ENDIF + ENDIF + +C SET THE LOOP FILTER + IF(.NOT.FOUNDLOOPFILTER.AND.USELOOPFILTER) THEN + DO I=NCTAMPS+1,NLOOPAMPS + IF(.NOT.ML5_0_ISZERO(ABS(AMPL(1,I))+ABS(AMPL(2,I)) + $ +ABS(AMPL(3,I)),(REF*1.0D-4),I)) THEN + IF(NTRY.EQ.1) THEN + GOODAMP(I,HELPICKED)=.TRUE. + ELSEIF(.NOT.GOODAMP(I,HELPICKED)) THEN + WRITE(*,*) '##W02 WARNING Inconsistent loop amp ',I + $ ,' for helicity ',HELPICKED,'.' + IF(LOOPINITSTARTOVER) THEN + WRITE(*,*) '##I01 INFO Initialization starting' + $ //' over because of inconsistency in the loop' + $ //' filter setup.' + NTRY=0 + ELSE + GOODAMP(I,HELPICKED)=.TRUE. + ENDIF + ENDIF + ENDIF + ENDDO + ENDIF + ELSEIF (.NOT.HELDOUBLECHECKED)THEN + IF ((.NOT.GOODHEL(HELPICKED)) + $ .AND.(.NOT.ML5_0_ISZERO(ABS(ANS(1))+ABS(ANS(2))+ABS(ANS(3)) + $ ,REF/DBLE(NCOMB),-1))) THEN + WRITE(*,*) '##W15 Helicity filter could not be' + $ //' successfully double checked.' + WRITE(*,*) '##One reason for this is that you have changed' + $ //' sensible parameters which affected what are the zero' + $ //' helicity configurations.' + WRITE(*,*) '##MadLoop will try to reset the Helicity' + $ //' filter with the next PS points it receives.' + NTRY=0 + OPEN(30,FILE=HELFILTERFN,ERR=349) + 349 CONTINUE + CLOSE(30,STATUS='delete') + ENDIF +C SET HELDOUBLECHECKED TO .TRUE. WHEN DONE +C even if it failed we do not want to redo the check +C afterwards if HELINITSTARTOVER=.FALSE. + IF (HELPICKED.EQ.NCOMB.AND.(NTRY.NE.0.OR..NOT.HELINITSTARTOVE + $R)) THEN + DONEHELDOUBLECHECK=.TRUE. + ENDIF + ENDIF + +C GOTO NEXT HELICITY OR FINISH + IF(HELPICKED.NE.NCOMB) THEN + HELPICKED=HELPICKED+1 + MP_DONE=.FALSE. + GOTO 200 + ELSE + ANS(1)=BUFFR(1) + ANS(2)=BUFFR(2) + ANS(3)=BUFFR(3) +C We add one here to the number of PS points used for building +C the reference scale for comparison (used only for +C loop-induced processes). + NPSPOINTS = NPSPOINTS+1 + IF(NTRY.EQ.0) THEN + NATTEMPTS=NATTEMPTS+1 + IF(NATTEMPTS.EQ.MAXATTEMPTS) THEN + WRITE(*,*) '##E01 ERROR Could not initialize the filters' + $ //' in ',MAXATTEMPTS,' trials' + STOP + ENDIF + ENDIF + ENDIF + + ENDIF + + DO K=1,3 + ANS(K)=ANS(K)/DBLE(IDEN) + IF (USERHEL.NE.-1) THEN + ANS(K)=ANS(K)*HELAVGFACTOR + ELSE + DO J=1,NINITIAL + IF (POLARIZATIONS(J,0).NE.-1) THEN + ANS(K)=ANS(K)*BEAMS_HELAVGFACTOR(J) + ANS(K)=ANS(K)/POLARIZATIONS(J,0) + ENDIF + ENDDO + ENDIF + ENDDO + + IF(.NOT.CHECKPHASE.AND.HELDOUBLECHECKED.AND.(CTMODERUN.LE.-1)) + $ THEN + STAB_INDEX=STAB_INDEX+1 + IF(DOING_QP_EVALS) THEN + QP_RES(1,STAB_INDEX)=ANS(1) + QP_RES(2,STAB_INDEX)=ANS(2) + QP_RES(3,STAB_INDEX)=ANS(3) + ELSE + DP_RES(1,STAB_INDEX)=ANS(1) + DP_RES(2,STAB_INDEX)=ANS(2) + DP_RES(3,STAB_INDEX)=ANS(3) + ENDIF + + IF(DOING_QP_EVALS) THEN + BASIC_CT_MODE=4 + ELSE + BASIC_CT_MODE=1 + ENDIF + +C BEGINNING OF THE DEFINITIONS OF THE DIFFERENT EVALUATION +C METHODS + + IF(.NOT.EVAL_DONE(2)) THEN + EVAL_DONE(2)=.TRUE. + CTMODE=BASIC_CT_MODE+1 + GOTO 200 + ENDIF + + CTMODE=BASIC_CT_MODE + + IF(.NOT.EVAL_DONE(3).AND. + $ ((DOING_QP_EVALS.AND.NROTATIONS_QP.GE.1) + $ .OR.((.NOT.DOING_QP_EVALS).AND.NROTATIONS_DP.GE.1)) ) THEN + EVAL_DONE(3)=.TRUE. + CALL ML5_0_ROTATE_PS(PS,P,1) + IF (DOING_QP_EVALS) CALL ML5_0_MP_ROTATE_PS(MP_PS,MP_P,1) + GOTO 200 + ENDIF + + IF(.NOT.EVAL_DONE(4).AND. + $ ((DOING_QP_EVALS.AND.NROTATIONS_QP.GE.2) + $ .OR.((.NOT.DOING_QP_EVALS).AND.NROTATIONS_DP.GE.2)) ) THEN + EVAL_DONE(4)=.TRUE. + CALL ML5_0_ROTATE_PS(PS,P,2) + IF (DOING_QP_EVALS) CALL ML5_0_MP_ROTATE_PS(MP_PS,MP_P,2) + GOTO 200 + ENDIF + + CALL ML5_0_ROTATE_PS(PS,P,0) + IF (DOING_QP_EVALS) CALL ML5_0_MP_ROTATE_PS(MP_PS,MP_P,0) + +C END OF THE DEFINITIONS OF THE DIFFERENT EVALUATION METHODS + + IF(DOING_QP_EVALS) THEN + CALL ML5_0_COMPUTE_ACCURACY(QP_RES,N_QP_EVAL,ACC,ANS(1)) + ACCURACY(0)=ACC + RET_CODE_H=3 + IF(ACC.GE.MLSTABTHRES) THEN + RET_CODE_H=4 + NEPS=NEPS+1 + CALL ML5_0_COMPUTE_ACCURACY(DP_RES,N_DP_EVAL,TEMP1,TEMP) + WRITE(*,*) '##W03 WARNING An unstable PS point was', + $ ' detected.' + WRITE(*,*) '##(DP,QP) accuracies : (',TEMP1,',',ACC,')' + WRITE(*,*) '##Best estimate (fin,1eps,2eps) :',(ANS(I),I=1 + $ ,3) + IF(NEPS.LE.10) THEN + WRITE(*,*) '##Double precision evaluations :',(DP_RES(1 + $ ,I),I=1,N_DP_EVAL) + WRITE(*,*) '##Quad precision evaluations :',(QP_RES(1 + $ ,I),I=1,N_QP_EVAL) + WRITE(*,*) '##PS point specification :' + WRITE(*,*) '##Renormalization scale MU_R=',MU_R + DO I=1,NEXTERNAL + WRITE (*,'(i2,1x,4e27.17)') I, P(0,I),P(1,I),P(2,I) + $ ,P(3,I) + ENDDO + ENDIF + IF(NEPS.EQ.10) THEN + WRITE(*,*) '##Further output of the details of these' + $ //' unstable PS points will now be suppressed.' + ENDIF + ENDIF + ELSE + CALL ML5_0_COMPUTE_ACCURACY(DP_RES,N_DP_EVAL,ACC,ANS(1)) + IF(ACC.GE.MLSTABTHRES) THEN + DOING_QP_EVALS=.TRUE. + EVAL_DONE(1)=.TRUE. + DO I=2,MAXSTABILITYLENGTH + EVAL_DONE(I)=.FALSE. + ENDDO + STAB_INDEX=0 + CTMODE=4 + GOTO 200 + ELSE + ACCURACY(0)=ACC + RET_CODE_H=2 + ENDIF + ENDIF + ELSE + RET_CODE_H=1 + ACCURACY=-1.0D0 + ENDIF + + 9999 CONTINUE + +C Finalize the return code + IF (MP_DONE_ONCE) THEN + RET_CODE_T=2 + ELSE + RET_CODE_T=1 + ENDIF + IF(CHECKPHASE.OR..NOT.HELDOUBLECHECKED) THEN + RET_CODE_H=1 + RET_CODE_T=RET_CODE_T+2 + ACCURACY=-1.0D0 + ENDIF + IF (RET_CODE_H.EQ.4) THEN + RET_CODE_U=0 + ELSE + RET_CODE_U=1 + ENDIF + +C Reinitialize the default threshold if it was specified by the +C user + IF (USER_STAB_PREC.GT.0.0D0) THEN + MLSTABTHRES=MLSTABTHRES_BU + CTMODEINIT=CTMODEINIT_BU + ENDIF + +C Reinitialize the Lorentz test if it had been disabled because +C spin-2 particles are in the external states. + NROTATIONS_DP = NROTATIONS_DP_BU + NROTATIONS_QP = NROTATIONS_QP_BU + +C Conform to the returned synthax of split orders even though the +C default output does not support it (this then done only for +C compatibility purpose). + ANSRETURNED(0,0)=ANS(0) + ANSRETURNED(1,0)=ANS(1) + ANSRETURNED(2,0)=ANS(2) + ANSRETURNED(3,0)=ANS(3) + +C Reinitialize the check phase logicals and the filters if check +C bypassed + IF (BYPASS_CHECK) THEN + CHECKPHASE = OLD_CHECKPHASE + HELDOUBLECHECKED = OLD_HELDOUBLECHECKED + DO I=1,NCOMB + GOODHEL(I)=OLD_GOODHEL(I) + ENDDO + DO I=1,NCOMB + DO J=1,NLOOPAMPS + GOODAMP(J,I)=OLD_GOODAMP(J,I) + ENDDO + ENDDO + ENDIF + + END + + SUBROUTINE ML5_0_COMPUTE_ACCURACY(FULLLIST, LENGTH, ACC, + $ ESTIMATE) + IMPLICIT NONE +C +C PARAMETERS +C + INTEGER MAXSTABILITYLENGTH + COMMON/ML5_0_STABILITY_TESTS/MAXSTABILITYLENGTH +C +C ARGUMENTS +C + REAL*8 FULLLIST(3,MAXSTABILITYLENGTH) + INTEGER LENGTH + REAL*8 ACC, ESTIMATE(3) +C +C LOCAL VARIABLES +C + LOGICAL MASK(MAXSTABILITYLENGTH) + LOGICAL MASK3(3) + DATA MASK3/.TRUE.,.TRUE.,.TRUE./ + INTEGER I,J + REAL*8 AVG + REAL*8 DIFF + REAL*8 ACCURACIES(3) + REAL*8 LIST(MAXSTABILITYLENGTH) + +C ---------- +C BEGIN CODE +C ---------- + DO I=1,LENGTH + MASK(I)=.TRUE. + ENDDO + DO I=LENGTH+1,MAXSTABILITYLENGTH + MASK(I)=.FALSE. + ENDDO + + DO I=1,3 + DO J=1,MAXSTABILITYLENGTH + LIST(J)=FULLLIST(I,J) + ENDDO + DIFF=MAXVAL(LIST,1,MASK)-MINVAL(LIST,1,MASK) + AVG=(MAXVAL(LIST,1,MASK)+MINVAL(LIST,1,MASK))/2.0D0 + ESTIMATE(I)=AVG + IF (AVG.EQ.0.0D0) THEN + ACCURACIES(I)=DIFF + ELSE + ACCURACIES(I)=DIFF/ABS(AVG) + ENDIF + ENDDO + +C The technique below is too sensitive, typically to +C unstablities in very small poles +C ACC=MAXVAL(ACCURACIES,1,MASK3) +C The following is used instead + ACC = 0.0D0 + AVG = 0.0D0 + DO I=1,3 + ACC = ACC + ACCURACIES(I)*ABS(ESTIMATE(I)) + AVG = AVG + ESTIMATE(I) + ENDDO + ACC = ACC / ( ABS(AVG) / 3.0D0) + +C If NaN are present in the evaluation, automatically set the +C accuracy to 1.0d99. + DO I=1,3 + DO J=1,MAXSTABILITYLENGTH + IF (ISNAN(FULLLIST(I,J))) THEN + ACC = 1.0D99 + ENDIF + ENDDO + ENDDO + + END + + SUBROUTINE ML5_0_SET_N_EVALS(N_DP_EVALS,N_QP_EVALS) + + IMPLICIT NONE + INTEGER N_DP_EVALS, N_QP_EVALS + + INCLUDE 'MadLoopParams.inc' + + IF(CTMODERUN.LE.-1) THEN + N_DP_EVALS=2+NROTATIONS_DP + N_QP_EVALS=2+NROTATIONS_QP + ELSE + N_DP_EVALS=1 + N_QP_EVALS=1 + ENDIF + + IF(N_DP_EVALS.GT.20.OR.N_QP_EVALS.GT.20) THEN + WRITE(*,*) '##ERROR:: Increase hardcoded maxstabilitylength.' + STOP + ENDIF + + END + + +C THIS SUBROUTINE SIMPLY SET THE GLOBAL PS CONFIGURATION GLOBAL +C VARIABLES FROM A GIVEN VARIABLE IN DOUBLE PRECISION + SUBROUTINE ML5_0_SET_MP_PS(P) + + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + REAL*16 MP_PS(0:3,NEXTERNAL),MP_P(0:3,NEXTERNAL) + COMMON/ML5_0_MP_PSPOINT/MP_PS,MP_P + REAL*8 P(0:3,NEXTERNAL) + + DO I=1,NEXTERNAL + DO J=0,3 + MP_PS(J,I)=P(J,I) + ENDDO + ENDDO + CALL ML5_0_MP_IMPROVE_PS_POINT_PRECISION(MP_PS) + DO I=1,NEXTERNAL + DO J=0,3 + MP_P(J,I)=MP_PS(J,I) + ENDDO + ENDDO + + END + + SUBROUTINE ML5_0_SET_COUPLINGORDERS_TARGET(SOTARGET) + IMPLICIT NONE +C +C This routine can be accessed by an external user to set the +C squared split order target. +C This functionality is only available in the optimized mode, but +C for compatibility +C purposes, a dummy version is also put in this default output. +C +C +C ARGUMENTS +C + INTEGER SOTARGET +C ---------- +C BEGIN CODE +C ---------- + WRITE(*,*) '##WARNING:: Ignored, the possibility of selecting' + $ //' specific squared order contributions is not available in' + $ //' the default mode.' + + END + + SUBROUTINE ML5_0_FORCE_STABILITY_CHECK(ONOFF) +C +C This function can be called by the MadLoop user so as to always +C have stability +C checked, even during initialisation, when calling the *_thres +C routines. +C + LOGICAL ONOFF + + LOGICAL BYPASS_CHECK, ALWAYS_TEST_STABILITY + DATA BYPASS_CHECK, ALWAYS_TEST_STABILITY /.FALSE.,.FALSE./ + COMMON/ML5_0_BYPASS_CHECK/BYPASS_CHECK, ALWAYS_TEST_STABILITY + + ALWAYS_TEST_STABILITY = ONOFF + + END + + SUBROUTINE ML5_0_GET_ANSWER_DIMENSION(ANSDIM) +C +C Simple subroutine which returns the upper bound of the second +C dimension of the +C quantity ANS(0:3,0:ANSDIM) returned by MadLoop. As long as the +C default output +C cannot handle split orders, this ANSDIM will always be 0. +C + INCLUDE 'nsquaredSO.inc' + + INTEGER ANSDIM + + ANSDIM=NSQUAREDSO + + END + + SUBROUTINE ML5_0_GET_NSQSO_LOOP(NSQSO) +C +C Simple subroutine returning the number of squared split order +C contributions returned in ANS when calling sloopmatrix +C + INCLUDE 'nsquaredSO.inc' + + INTEGER NSQSO + + NSQSO=NSQUAREDSO + + END + + SUBROUTINE ML5_0_SET_LEG_POLARIZATION(LEG_ID, LEG_POLARIZATION) + IMPLICIT NONE +C +C ARGUMENTS +C + INTEGER LEG_ID + INTEGER LEG_POLARIZATION +C +C LOCALS +C + INTEGER I + INTEGER LEG_POLARIZATIONS(0:5) +C ---------- +C BEGIN CODE +C ---------- + + IF (LEG_POLARIZATION.EQ.-10000) THEN + LEG_POLARIZATIONS(0)=-1 + DO I=1,5 + LEG_POLARIZATIONS(I)=-10000 + ENDDO + ELSE + LEG_POLARIZATIONS(0)=1 + LEG_POLARIZATIONS(1)=LEG_POLARIZATION + DO I=2,5 + LEG_POLARIZATIONS(I)=-10000 + ENDDO + ENDIF + CALL ML5_0_SET_LEG_POLARIZATIONS(LEG_ID,LEG_POLARIZATIONS) + + END + + SUBROUTINE ML5_0_SET_LEG_POLARIZATIONS(LEG_ID, LEG_POLARIZATIONS) + IMPLICIT NONE +C +C CONSTANTS +C + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INTEGER NPOLENTRIES + PARAMETER (NPOLENTRIES=(NEXTERNAL+1)*6) + INTEGER NCOMB + PARAMETER (NCOMB=16) +C +C ARGUMENTS +C + INTEGER LEG_ID + INTEGER LEG_POLARIZATIONS(0:5) +C +C LOCALS +C + INTEGER I,J + LOGICAL ALL_SUMMED_OVER +C +C GLOBALS +C +C Entry 0 of the first dimension is all -1 if there is no +C polarization requirement. +C Then for each leg with ID legID, it is either summed over if +C POLARIZATIONS(legID,0) is -1, or the list of helicity considered +C for that +C leg is POLARIZATIONS(legID,1: POLARIZATIONS(legID,0) ). + INTEGER POLARIZATIONS(0:NEXTERNAL,0:5) + DATA ((POLARIZATIONS(I,J),I=0,NEXTERNAL),J=0,5)/NPOLENTRIES*-1/ + COMMON/ML5_0_BEAM_POL/POLARIZATIONS + + INTEGER BORN_POLARIZATIONS(0:NEXTERNAL,0:5) + COMMON/ML5_0_BORN_BEAM_POL/BORN_POLARIZATIONS + +C ---------- +C BEGIN CODE +C ---------- + + IF (LEG_POLARIZATIONS(0).EQ.-1) THEN + DO I=0,5 + POLARIZATIONS(LEG_ID,I)=-1 + ENDDO + ELSE + DO I=0,LEG_POLARIZATIONS(0) + POLARIZATIONS(LEG_ID,I)=LEG_POLARIZATIONS(I) + ENDDO + DO I=LEG_POLARIZATIONS(0)+1,5 + POLARIZATIONS(LEG_ID,I)=-10000 + ENDDO + ENDIF + + ALL_SUMMED_OVER = .TRUE. + DO I=1,NEXTERNAL + IF (POLARIZATIONS(I,0).NE.-1) THEN + ALL_SUMMED_OVER = .FALSE. + EXIT + ENDIF + ENDDO + IF (ALL_SUMMED_OVER) THEN + DO I=0,5 + POLARIZATIONS(0,I)=-1 + ENDDO + ELSE + DO I=0,5 + POLARIZATIONS(0,I)=0 + ENDDO + ENDIF + + DO I=0,NEXTERNAL + DO J=0,5 + BORN_POLARIZATIONS(I,J) = POLARIZATIONS(I,J) + ENDDO + ENDDO + + + RETURN + + END + + SUBROUTINE ML5_0_SLOOPMATRIXHEL_THRES(P,HEL,ANS,PREC_ASKED + $ ,PREC_FOUND,RET_CODE) + IMPLICIT NONE +C +C CONSTANTS +C + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INCLUDE 'nsquaredSO.inc' +C +C ARGUMENTS +C + REAL*8 P(0:3,NEXTERNAL) + REAL*8 ANS(0:3,0:NSQUAREDSO) + INTEGER HEL,RET_CODE + REAL*8 PREC_ASKED,PREC_FOUND(0:NSQUAREDSO) +C +C GLOBAL VARIABLES +C + REAL*8 USER_STAB_PREC + COMMON/ML5_0_USER_STAB_PREC/USER_STAB_PREC + + INTEGER I + + INTEGER H,T,U + REAL*8 ACCURACY(0:NSQUAREDSO) + COMMON/ML5_0_ACC/ACCURACY,H,T,U + + LOGICAL BYPASS_CHECK, ALWAYS_TEST_STABILITY + COMMON/ML5_0_BYPASS_CHECK/BYPASS_CHECK, ALWAYS_TEST_STABILITY + +C ---------- +C BEGIN CODE +C ---------- + USER_STAB_PREC = PREC_ASKED + CALL ML5_0_SLOOPMATRIXHEL(P,HEL,ANS) + IF(ALWAYS_TEST_STABILITY.AND.(H.EQ.1.OR.ACCURACY(0).LT.0.0D0)) + $ THEN + BYPASS_CHECK = .TRUE. + CALL ML5_0_SLOOPMATRIXHEL(P,HEL,ANS) + BYPASS_CHECK = .FALSE. +C Make sure we correctly return an initialization-type T code + IF (T.EQ.2) T=4 + IF (T.EQ.1) T=3 + ENDIF + +C Reset it to default value not to affect next runs + USER_STAB_PREC = -1.0D0 + DO I=0,NSQUAREDSO + PREC_FOUND(I)=ACCURACY(I) + ENDDO + RET_CODE=100*H+10*T+U + + END + + SUBROUTINE ML5_0_SLOOPMATRIX_THRES(P,ANS,PREC_ASKED,PREC_FOUND + $ ,RET_CODE) +C +C Inputs are: +C P(0:3, Nexternal) double :: Kinematic configuration +C (E,px,py,pz) +C PEC_ASKED double :: Target relative accuracy, -1 for +C default +C +C Outputs are: +C ANS(3) double :: Result (finite, single pole, +C double pole) +C PREC_FOUND double :: Relative accuracy estimated for +C the result +C Returns -1 if no stab test could be performed. +C RET_CODE integer :: Return code. See below for details +C +C Return code conventions: RET_CODE = H*100 + T*10 + U +C +C H == 1 +C Stability unknown. +C H == 2 +C Stable PS (SPS) point. +C No stability rescue was necessary. +C H == 3 +C Unstable PS (UPS) point. +C Stability rescue necessary, and successful. +C H == 4 +C Exceptional PS (EPS) point. +C Stability rescue attempted, but unsuccessful. +C +C T == 1 +C Default computation (double prec.) was performed. +C T == 2 +C Quadruple precision was used for this PS point. +C T == 3 +C MadLoop in initialization phase. Only double precision used. +C T == 4 +C MadLoop in initialization phase. Quadruple precision used. +C +C U is a number left for future use (always set to 0 for now). +C example: TIR vs OPP usage. +C + IMPLICIT NONE +C +C CONSTANTS +C + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INCLUDE 'nsquaredSO.inc' +C +C ARGUMENTS +C + REAL*8 P(0:3,NEXTERNAL) + REAL*8 ANS(0:3,0:NSQUAREDSO) + REAL*8 PREC_ASKED,PREC_FOUND(0:NSQUAREDSO) + INTEGER RET_CODE +C +C GLOBAL VARIABLES +C + REAL*8 USER_STAB_PREC + COMMON/ML5_0_USER_STAB_PREC/USER_STAB_PREC + + INTEGER I + + INTEGER H,T,U + REAL*8 ACCURACY(0:NSQUAREDSO) + COMMON/ML5_0_ACC/ACCURACY,H,T,U + + LOGICAL BYPASS_CHECK, ALWAYS_TEST_STABILITY + COMMON/ML5_0_BYPASS_CHECK/BYPASS_CHECK, ALWAYS_TEST_STABILITY + +C ---------- +C BEGIN CODE +C ---------- + USER_STAB_PREC = PREC_ASKED + CALL ML5_0_SLOOPMATRIX(P,ANS) + IF(ALWAYS_TEST_STABILITY.AND.(H.EQ.1.OR.ACCURACY(0).LT.0.0D0)) + $ THEN + BYPASS_CHECK = .TRUE. + CALL ML5_0_SLOOPMATRIX(P,ANS) + BYPASS_CHECK = .FALSE. +C Make sure we correctly return an initialization-type T code + IF (T.EQ.2) T=4 + IF (T.EQ.1) T=3 + ENDIF + +C Reset it to default value not to affect next runs + USER_STAB_PREC = -1.0D0 + DO I=0,NSQUAREDSO + PREC_FOUND(I)=ACCURACY(I) + ENDDO + RET_CODE=100*H+10*T+U + + END + diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/loop_matrix.ps b/UNITTEST_proc/SubProcesses/P0_gg_ttx/loop_matrix.ps new file mode 100644 index 0000000000000000000000000000000000000000..25a20ffd0611c7b8ea5e09d127993fe95ff481fd GIT binary patch literal 46706 zcmeHQ>2F-gasU4QisugtXn}~Fcg~Cf173U0Bu4D`$cZ2@M&yVjOmXDlXjg=w{O$Qw zRUg&e)#Q-TdbQ39yAnCCySnbH`}KVBli&UE5b)1qzZFAVs4cmD3p_V#eLyFJ|fwEc(e%{SY__4x*mez&>Y;-hxPxS#xH zbMg24&D*Qyi{^{=YzqeZ9HdZ{FOs7yHe(x9zL@)(@NhwE4|1fBxHl`ez>h zuXjM9J^R&v{`NOt{kHx34`2N|fPB@y-S22R&HH-u&Gkk5>y!46@7}!G?(f>ej)AJh zF5F@#?Thm-+itz?@$la;_Ih{Q_9sjK@xV*|atAmdsomUOw10WGy*pqSgT<`&>yuxf zxRrkX?$0Ni^OK8r`>V|xOl?ljZg+2Y*EF|Vv=`ggEk4>~g~|Q$_PQNTy0M$q{X7lR znm(p!`!~Cb_QS=yx9u=v;`KM}>zmzf&%eESchlazd-ajWo}S%ZU*5JK7VYJ>{m^}E zKfJ_W*RQuXcUu_&Xs6b&N^PtWe%T!xrF1v2kx6+kwg(p^XPVZ=KJ_tbB2Lu_yF8)&j8}=-u=uB1-1uX zr)$pm-@YZO;csHtt2>@X3(8ZH5aD_ujF!LmEZd&{7Tj*Z8Gg1Wb7O>Me%D?eTFl3Q zFa|#{ZlnVZ$p|n=`cMNNST4d)+nxpN29v5VnMB^39c*^jF4_*uINfcq4ABIb*O66@ z={MK6G~r|Wdbe*Nl--}V_ywRzjiIw|P5Icua^i8qa^k59i*zXp3(~lO{R3?fvt@jV zHNx7nEo-T8`2D$1OTwioTCz^pnU`8B_m~6j@KBzEl}S6W1hbNOPyg#V`@LJ|Tr}a` zTQMt!6Fw7dNzLnU1(j06h|V*hO$2QYaF#;I;fhqU$544B>Y5D$FBa_$tO}!{r&k^Q zLXHg5q~G{2axw(mX#_EF(Lmj3l8nGFVG@7TvoG?Knrkxri^G+gLeIoIIdlzUAu|z! zagZ>dOgA%@fCi1CIo(RUBK#+b>}&Gxe^Yfj}l0T{{#S`vxR4c zhrut*x5HI)zPnQ&h-W*-wm19z?%U>r_ZaNg5f>OM^5TdB__^6T2XTgHB54{aqrxW` zUmr_!FxG(RAlx6=Lg`Zv|Mm6FO>{hOuXcysZS&znG{bXDQ&YY7N^mjqqSmV5#Jf42H-m&!addJXz@l5)Eu<}Qo;GBizAX@3Q zQGLR8n`z2T^Fi`LN;nZi_d6Jqq?BYq2!3!F>?pjW6-#-drsS3)a7o3311HaM&F=jP z8koZUi0mg|E$$7Wn85*Sc+d)b_-?W|B9q(`PpDWqhg|Pbfx8R_?i#wO&o$`me@II7 zKPZq49tjFEsOZ)%Z{Cqt2-R+=(hd~@)@r0K>-?Irylaf|j(wPv8Af@>#gzBy zUY{js$edW-HBu7B@{U!&nuAEF>oV%qurB~9z993TVS1ywCtP-^VHymTcdiWPk^@Zh z&?@C!6UsZ%_lL?mf=iKw%RA~OV0^W_Yx0_qN)R?F&`0x#CxM4x1)dQbsp@rgC17(U zhhl59Kfgs-#y=lXDsmCz^^u@*3g8M=XxXJ;i6;`iJ(TdoRVk8~oO}1ej)Kr~w(sD& z@XQZ5`N_X?ecy83dbvkadAG+CZlHyQuC6aHxp7pn&&-4XN`PA@ihS2wr8aX0_vK9GO@8wCW2q+hbgBz@H)GI=IA z>Ol*Wk1FoDar1{se-K#kut8kmllCkvbr2iBV3F(Nq z4!ANj>!;cQ7urCPMKwab+De)%T~DvxwA^t4w<-In)qpF_co(K(?6mu-4V&9>0hju+ zX+M>sv>9+iAN!bq+i<`QwPc9)gj(4}Mg1#H#nyy3--Tb0SB8k0CbE*n^59O2^fNLghoByN6)7U)d;ntHa>vg7;@ z3zGUdD_}K1v7<-8Hh9FIHw7^-1d4{D0dJ+0PJnHSpaxrN#0kW7hS~XPy#U!i{Rh&R z6bT6Ufan!l{xRW>TO*tscYbT+yG*#Bvnx?oYPUP$w}{9=WJ*gpJ!u{p5f#dC7OpTq z=g+x(<2>GZ5lX^?nzO?QYR*ZIQ}ZnSry?_^|FTj&{U^s6(*F=RYUzJrFE}*7y9Ce8 zFCOtf60HtugFs@H{zOV?$%xRQ6Z2xWaTL{`NV)BbPXB-<#kHjV#DpqCDK_h&2~_1= z;DAsdx(yvc2+A$)$EAh5eIeUCEa}j9z(Dv%p7j2PU8{2&jHr8pi8MlI$JKw#%rwveUcXO5b);DT!ir}!p35O4o_?*An?{VmZPj58XV7a}! z*&Ij{(em?qS9s`_!kOwCoJq7%BOB=JPLp`zp z251Dp&+$+0u6EywOd@;vvmB~0Vm#BKIlB~HjUA!XiNbbBK~?xG*$2b1+0YrRCobOeZ^CJq9K)-OE4h=-k-r>)Q)9J0v5`>Gi=s{l~-R=K4H)e0SfT{_+0JtKCid zpgH|^dw~N~&FP2s^d6rwtr{7Q zNGR?tfb|>e4Bmg*=q-1CLLd02yiM=tp)VOe_n&ALn$w%@?Imm$6N9Mk!;b{r%c(hi|LzuAiIIMe zPn_@N0pgJZCJ!*9YlS8r@Nzs^h17-xj3_E3Rh}dEs`=&gUQd7G<5Y)$DUd<97jd=? zmPU#oQV`CChXq~JiJazO$A?0zIn4;m1^_@pSoWCaCzNH+8}ZwMvfwF3pLF0Pz_5yP zPX#{n6LChpnW%Tez_<^q6Ce^`MC7}5oR`9Q2{$X-@L)l=#DRVA zpbkf^uVLaye+p+MaJmzS*TAQrmM8sc7{|r5>iTi++i5+V^xbM2SL<%k&BM_4EFcln zncE2mj{UfzbMMQ3(XSVCKXfAy?v^LrV%;ytahevZ4mFEZTFr~Y{{%+1I4Pg3IzXJu zRkm!HIfjWElM?fJIiD<7-8glN)p|9|%QnGwQDQr-PFCy1vY)1LTz4y!fdSjFriJXh z?y{A_#34-7V$p~zP4Bx$)Wzv>I}M}OSQH`rss-Y9SPt(%kZNT^+ZVt8<<~zO|E~T0 zufG1-A`G5jT(CT787y(4pGoHxyQWTza6Kl9a|jSHja6&e&6sVFk2gwa3DzCGoFadm zWswPTGqqFZO|V*^sZiF4E*uL7&7g>BE}zB~#xQLDPGs>EqHETG8|lG=Xl8G=0xMPo(uq1G*J!@;Iz(8lWfk0&ty}OFxoo zwBxdBE^x9uVqGzpWC_M|fKVnK7yDlDgws%p8e@xKHjIl_fC&IaXb;MPHP^OOE(T zEThx%)qFB*7o_CkeL7;HMlMR9+(@y8B7b!Jg{~)SL>-0TSvx8$PLOxMAf`C=6mqynYei2Bcuh+G2PoUJ%q|F~y6)>2bb9$%~3A zJHT)l5LdE_B4iX^3`l*H&KA5Fg^3AB=jhX+6$?NrdNL<}kfD;lHy(&(DPeW+-^tu{+ad|JDS*QC zD4`6vvY>|BElvjg2RSmzCmXKwJ_OtHJ~jIK#VTE+L&i=aPU9f~z6T7g?olcdJ80=D zIIk^~`uFRUT}a?LA6J&5RHt=O1!aMzJo=UDng)+Wb_yBPDCBc{q*j_XwY~*~RilS- z&#T3{o99)BcZgRLBFB7!PgXt3p&ndWjKNH(E?f5}-EvrB#&TE>Ll1d&0J2`dXO4@x z>uT-hM zNvjv6fgIv-kyC6Txm0OTGN&vrk@-U+chR>Zb89)4x%D8I`3U>d{9Xc&s>lt1;yaB8 zg~1yuWxo0l!Z>k~yqW>GaMr^LveADY^3{%$6=yvn1JaPFi9#;9iiR?tQL^;hS4Wy8 zqhYEl%P44YV2N1fM_je5b*rx0pg;svBU!2HC{Sgz@-Ms z$ciVRt|9d>L;JPI*3$EPu79xN3 zq{)aGrJxG&kq9?W7??r~{G`&LL%Ri~!8{}xy$ayzT){@5f&;2F=$2~%RB2%NM4;B~ zTq^r_nLs+U;sDBsKh0^DXF28x;Q%6w4R0$EAT!d*U!~z~WC9a<;5rkCNmw)|ieB6l z1UGeTg%cO-lu8+Szywh!GgZpvqF1F`X!v+p&UjF43mDOPMunpAh#F|YW3F2d@|LKz zQ0kW=!Nf>1B?~Sus2N$N0n5kQt`#$_E>{Li>BTEFTpEDFq!KJ^FeE)7jFj$TPbAl% zc1G}o#|X)Pl#6c!Ez>SlbZ-`6ET0-u3Kf?H%vsl8t^PT*Ww zgDgMGXgD()>wWtw6v=N0DJ2@(jZDJHeB9PWQlCd>V9_S~EoEm)Xwy8Fjja*M1tb%E zQFPrtDM*`uu_#z8Z{U)GbZ8|hFkG1Eu<@WUG9&h6x*Z9i*u#zDGKd#&jUZmPT^GbF z##<$$bkVX=q=e#J^pI_5MVew$y#`IG+k{4HqHYgwLAeTaNc&bXDXOh#5L`GV7gUFQ zZz?z<3kdt0GKVBQy7i)4cB|zQX9%=~jnlg58I9C~UE@>)PFSo~wZg*46vq`xc)d`t zl4ygZWMt)4{FQW#K1bcFIVG#OHETIGed|H)w+$o8-FA?R?+m1-9lZduojCR>+XhBb z(4(Q82-a|L(mYa1PE}{#C8SP&P2!Iv1^rx;c{Bw0OKJjDu~Q=Nj7avW_aO{Ciq@T# z6y&|T$eAic>jC#8HOWR+kToQuKLaa2lO8*hVTAJz2er~I9SNKr_U&{MA8D!rk(_|& zRr=eHXm%uj(7(;Li&Tp4c68`SoQm4fA6XLOR&o_9g-a*9Rn#ufq^Ts%Ck09SPk965 zTvRgj_?$raUdEh49;0micSzDS(or7dqH9h4T)0LakP9OM_Iv8bclE2y=#nak#<8ztXvL6=mj8e^n0^2)|KU@% z{0$#0=MoJcTpUD~v;i>DWqM zVK`^$Xc`ZESMBBE1ZT+Nt33mb6J>=KbxTY_Kwhoy4t&Ji!h=&LpgHat^N*S$@1|?@=>n zG2?Y6w29Dy8<%Ko4@iWUYaH*x(bayyMoUzf#HC}GJVgPVhm9vV1XYW+WrP<&tE7n< zfN*{26)u)A!&PEv{eWIkhB{tKI_Vd9Jz>VI85{gdg?qHLzC@j}|8%KAcIrKVwZ5e>`ePUWvsL}hvSkiPE>R2zlHal&+L#q^DirnK+N>PZwp5$OBr zD8ST7j7Sm%yw78cKv1vJs%a`a1Jx}M1D-4d!od;wS%t^}#X*wmm9JE&w9~h!x$$i1 zxwSg?qOAuEM4@s-lR8FdlH>Q$g)iC!RWXi56JAamj_`F#HI-*X6Tk_mrs#@W6Ala% zu`P|#3bgMI2)03T(Yg9Ko*Jl%s$I9ck zX2jW*p;nxPrcVyj=lg%rztv#;6}tMCeB?!vB2y`MoFpO1H~*9yc=#oO&Nv=;j2kGn z3`SfF_ygE77{B8!gGamTdEsyLH?pJSQI?3opH+|D2w=WJnssrE_D0r?j#QSd0D8$n zw-#1bd!sm7ZM8S%McUrLMPuO(ljz?NCyMsQgk&PcAgTBt&%3{?xj5k<*lst z209u^djofg1=K@6Xkoqt&FM;EVoa2)qO6jna}jslMzx6!#r-~ZzkCXmHY-&QWSoXf z$5xV{GFXV14NqRa7eQS&YGT*kL8s`-I}YVW{om|s4BTu7;owYR$3}Z2zv(H4ale@% zPz*&kL_{rps@jXUMg)jbbR$cef50zMFxNGCl1$K!h3alZ&rHn?r|3myQi#oHZWLlu zF4vu7&Eytct8Z?k_8Dy%wQ2N%PkGP5@O-itVR$}ypd7W^_a_xiO3Z)?Jl|)sCGp74 zizdqGKxCT{s)h!I-$&=#kWQ6Cd7vqjEwK?V)g)qz`Y4?NBCNWQf@j_EK>HUJ;J!03 zCYkn&sO;4>jR$_?EL;d^ZT)BBizZzKC=4Lo)pQy=|M{+&^2OnLq{^{JAD`1Eq_Sz_ zU}8G<==dyLGJJet((a5~VbW1IC_vZtAM$-h0-u$?Im4nbeDEURA#}w{CaTyQ4+@nx zLRY2~QE)_HtuaqKjry(>qgC?2W|ZH2fL#Rw(Z`&&UcE*&$zoYFEaU{OSevUP$GK}sdzIW0TSG%yX}nL_A(C_ zJbd2}U~_xih7G+y%HLI6h;qE3()N__k7wz=v0iYpz1QiGsE(Z40R!)z| zXoMlj4B;O4Dkf)fG{V7C;LfQMU%Idn!(|A2=`FUv>*hWQ*a~MTKifDSkbA3rYz?nxy6DLa-v! z@U7KT-@+&EdKbR6=r$X^mC6h_iJ&yvK3wfn-6(nj|DN6;reI&$7x8{3_(&tz*Zt+g z`y#X~bF(bF%Vow!=c{X<>Nyk zMepQq`kwO2{o-_;3w`6C+zZ23dFDNk%c~G~MDK-h`nK~FigXW$wBc}h70Z+Is_!2! zDc`lYQav#Gv%aJpJ%fm-s6=)$zT$)QQDA+PTvU)QEnUb-aO70FF`;#byz+N`+T9(< zS0~>Uit-*!_LfPs5kl~LIP4w~tQ>WZ7?wxIe?04+THoh<)*Z+5qxC(hjm(vbRM}Dn zxO18u0O(#Y+4rGKpHu4#>mhzp?Jo6R(Fi~qg1R9u(PMGv>eEW^NCTChT?ZwgXJ41D z;tJ5?MlTa8vsIq%FAJ|;g7NS{WX&=gKX>vnzxhNVXcUM8T?~-CW+G)-afa5YZU@|6 z``qf54&iBa>Jm|0Ak~-CF2YlV80i67PxU$?S2a|uhoF=0*Px>h0_gRN@*i${YN#W< z*x*hOEBr^?4MZzcZ_3y6#BB)=kUQ#Y%SX-taxfRc1?j08WClhWO(Whh)UNCz=AaY0 zJLvwaFUlFP<$|+o@r!a$EZ{{3Ppiigj&h!iG+DWrHF(N zw^JFYAXxN;I*El@FDP0G(2I>^nXP#58_D$x8l>GzAcAz`CWyvKGgDaz-aaI6klzd( z5j3L7kBwgIwAAO^=rs-}9n*@E($Dok`9zHrkxGAPFA(~Z9~zDNL-CHAb6lepJw^A@ z^8*(6a1%~Y6vNTzY82(A=iCINvnLd}ZOJGWMo8&1nMmCT9f}nzlww*qr_t3YN-0=a zVZ^a41q~~dw{{B|8SgzGyWL{cSI6zPXjDqvAKYxAIF#h0baDD|yDbK~M{Txf5oyeo zD|W9wKd{;I@agEmI8=0u4HoU-xt%|8JJ@|m`ltQc%K1~agOQETIF-fUJ~s2;N-}Uv zbV)Ynqag^Y5YFGI#q+~cbr1qj>yYW?a9npl_8;aJkZFE+8iTJwwsZX{%25^K*!&^z ze9J-r5W(wN9p~~wdYV9YxWNEPL=NUv$itJV3XvQPA2Gre1N3%#z~)u-KplO_BQlEB zVjR!~#svi6IlhzyDeW5HJBb9n?|EMuvSQkmf9r6nm)siK4!7QkV~oeHZ^-B5#tUW?E1 z#nDdC*-eW9>n~UOb@ssQ)0@KVZ=Ugb5L^TGHmw_ z$q^`CE*o3P!v}8micot!v!1U}M5;_EE*HdtFuz2x;t(`g z%~EA2J$AMjMZDdrmWU`)xil2LAibW`@UT&`9< z3TRv(Ko^Q&vk3bsKbG<$W`Su0|1#)w01D zW(Y?zAPr382;F|z2px_UBh;+ZOK2SBg0yzdj41e!_0>DWS!gEes4*@Jm3lcW5wlQzEJ~Kcw>RsIwPJn}odq39rKnvF#Nzh^`79Jy zxmEOsQamz34M5T6vrzi(Hl=`yIG2T13|WJ9Kj+uJ_$+k7mtHHAjiy2x3yq+u!Id>&f2LYL!Jtk8j#o2EDqEj-2O z^3dE0V~$5Sk_l;G8b_Ch*3Ho2STRG*I=zH4!_noTxfw8GAsLD2k!ENl zcgI7DVAtN+0(c_HJK=vpb)bi1ID;4mWXx#=~CYsunvO#@7$YrAG*oqCRp73G6 KxxU%%oBsu__~W<$ literal 0 HcmV?d00001 diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/loop_num.f b/UNITTEST_proc/SubProcesses/P0_gg_ttx/loop_num.f new file mode 100644 index 0000000000..83387cc67e --- /dev/null +++ b/UNITTEST_proc/SubProcesses/P0_gg_ttx/loop_num.f @@ -0,0 +1,934 @@ +C THE CORE SUBROUTINE CALLED BY CUTTOOLS WHICH CONTAINS THE HELAS +C CALLS BUILDING THE LOOP + + SUBROUTINE ML5_0_LOOPNUM(Q,RES) + USE ALOHA_OBJECT +C +C CONSTANTS +C + INTEGER NCOMB + PARAMETER (NCOMB=16) + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INTEGER NBORNAMPS + PARAMETER (NBORNAMPS=3) + INTEGER NLOOPAMPS + PARAMETER (NLOOPAMPS=129) + INTEGER NWAVEFUNCS + PARAMETER (NWAVEFUNCS=10) + INTEGER MAXLCOUPLINGS + PARAMETER (MAXLCOUPLINGS=4) + COMPLEX*16 IMAG1 + PARAMETER (IMAG1=(0D0,1D0)) +C +C ARGUMENTS +C + COMPLEX*16 Q(0:3) + COMPLEX*16 RES +C +C LOCAL VARIABLES +C + COMPLEX*16 CFTOT + COMPLEX*16 BUFF + INTEGER I,H +C +C GLOBAL VARIABLES +C + INTEGER WE(NEXTERNAL) + INTEGER ID, SYMFACT, MULTIPLIER, AMPLNUM + COMMON/ML5_0_LOOP/WE,ID,SYMFACT,MULTIPLIER,AMPLNUM + + LOGICAL GOODHEL(NCOMB) + LOGICAL GOODAMP(NLOOPAMPS,NCOMB) + COMMON/ML5_0_FILTERS/GOODAMP,GOODHEL + + INTEGER NTRY + LOGICAL CHECKPHASE,HELDOUBLECHECKED + REAL*8 REF + COMMON/ML5_0_INIT/NTRY,CHECKPHASE,HELDOUBLECHECKED,REF + + INTEGER CF_D(NLOOPAMPS,NBORNAMPS) + INTEGER CF_N(NLOOPAMPS,NBORNAMPS) + COMMON/ML5_0_CF/CF_D,CF_N + + COMPLEX*16 AMP(NBORNAMPS,NCOMB) + COMMON/ML5_0_AMPS/AMP + TYPE(ALOHA) W(NWAVEFUNCS,NCOMB) + COMMON/ML5_0_WFCTS/W + + INTEGER HELPICKED + COMMON/ML5_0_HELCHOICE/HELPICKED + + RES=(0.0D0,0.0D0) + + DO H=1,NCOMB + IF (((HELPICKED.EQ.-1).OR.(HELPICKED.EQ.H)) + $ .AND.((CHECKPHASE.OR..NOT.HELDOUBLECHECKED).OR.(GOODHEL(H) + $ .AND.GOODAMP(AMPLNUM,H)))) THEN + CALL ML5_0_LOOPNUMHEL(-Q,BUFF,H) + DO I=1,NBORNAMPS + CFTOT=DCMPLX(CF_N(AMPLNUM,I)/DBLE(ABS(CF_D(AMPLNUM,I))) + $ ,0.0D0) + IF(CF_D(AMPLNUM,I).LT.0) CFTOT=CFTOT*IMAG1 + RES=RES+CFTOT*BUFF*DCONJG(AMP(I,H)) + ENDDO + ENDIF + ENDDO + RES=(RES*MULTIPLIER)/SYMFACT + + END + + SUBROUTINE ML5_0_LOOPNUMHEL(Q,RES,H) + USE ALOHA_OBJECT +C +C CONSTANTS +C + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INTEGER MAXLCOUPLINGS + PARAMETER (MAXLCOUPLINGS=4) + INTEGER NMAXLOOPWFS + PARAMETER (NMAXLOOPWFS=(NEXTERNAL+2)) + REAL*8 ZERO + PARAMETER (ZERO=0.D0) + INTEGER NWAVEFUNCS + PARAMETER (NWAVEFUNCS=10) + INTEGER NBORNAMPS + PARAMETER (NBORNAMPS=3) + INTEGER NLOOPAMPS + PARAMETER (NLOOPAMPS=129) + INTEGER NCOMB + PARAMETER (NCOMB=16) +C +C ARGUMENTS +C + COMPLEX*16 Q(0:3) + COMPLEX*16 RES + INTEGER H +C +C LOCAL VARIABLES +C + COMPLEX*16 BUFF(4) + TYPE(ALOHA) WL(NMAXLOOPWFS) + INTEGER I +C +C GLOBAL VARIABLES +C + COMPLEX*16 LC(MAXLCOUPLINGS) + COMPLEX*16 ML(NEXTERNAL+2) + COMMON/ML5_0_DP_LOOP/LC,ML + + INTEGER WE(NEXTERNAL) + INTEGER ID, SYMFACT,MULTIPLIER,AMPLNUM + COMMON/ML5_0_LOOP/WE,ID,SYMFACT,MULTIPLIER,AMPLNUM + + COMPLEX*16 AMP(NBORNAMPS,NCOMB) + COMMON/ML5_0_AMPS/AMP + TYPE(ALOHA) W(NWAVEFUNCS,NCOMB) + COMMON/ML5_0_WFCTS/W + +C ---------- +C BEGIN CODE +C ---------- + RES=(0.D0,0.D0) + IF (ID.EQ.1) THEN +C Loop diagram number 4 (might be others, just an example) + DO I=1,4 + CALL LCUT_V(Q(0),I,WL(2)) + CALL VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL VVV1LP0_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) + BUFF(I)=WL(4)%W(I) + ENDDO + CALL CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.2) THEN +C Loop diagram number 5 (might be others, just an example) + DO I=1,4 + CALL LCUT_V(Q(0),I,WL(2)) + CALL FFV1L_1(W(WE(1),H),WL(2),LC(1),ML(3),ZERO,WL(3)) + CALL FFV1LP0_3(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) + CALL VVV1LP0_1(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) + BUFF(I)=WL(5)%W(I) + ENDDO + CALL CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.3) THEN +C Loop diagram number 6 (might be others, just an example) + DO I=1,4 + CALL LCUT_AF(Q(0),I,WL(2)) + CALL FFV1LP0_3(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL FFV1L_2(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) + CALL FFV1L_2(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) + BUFF(I)=WL(5)%W(I) + ENDDO + CALL CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.4) THEN +C Loop diagram number 7 (might be others, just an example) + DO I=1,4 + CALL LCUT_AF(Q(0),I,WL(2)) + CALL FFV1LP0_3(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL FFV1L_2(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) + BUFF(I)=WL(4)%W(I) + ENDDO + CALL CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.5) THEN +C Loop diagram number 8 (might be others, just an example) + DO I=1,4 + CALL LCUT_V(Q(0),I,WL(2)) + CALL VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL FFV1L_2(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) + CALL FFV1LP0_3(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) + BUFF(I)=WL(5)%W(I) + ENDDO + CALL CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.6) THEN +C Loop diagram number 9 (might be others, just an example) + DO I=1,4 + CALL LCUT_F(Q(0),I,WL(2)) + CALL FFV1L_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL FFV1LP0_3(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) + CALL FFV1L_1(W(WE(3),H),WL(4),LC(3),ML(5),ZERO,WL(5)) + BUFF(I)=WL(5)%W(I) + ENDDO + CALL CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.7) THEN +C Loop diagram number 11 (might be others, just an example) + DO I=1,4 + CALL LCUT_V(Q(0),I,WL(2)) + CALL VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL FFV1L_1(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) + CALL FFV1LP0_3(W(WE(3),H),WL(4),LC(3),ML(5),ZERO,WL(5)) + BUFF(I)=WL(5)%W(I) + ENDDO + CALL CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.8) THEN +C Loop diagram number 12 (might be others, just an example) + DO I=1,4 + CALL LCUT_AF(Q(0),I,WL(2)) + CALL FFV1L_2(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL FFV1LP0_3(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) + CALL FFV1L_2(W(WE(3),H),WL(4),LC(3),ML(5),ZERO,WL(5)) + BUFF(I)=WL(5)%W(I) + ENDDO + CALL CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.9) THEN +C Loop diagram number 15 (might be others, just an example) + DO I=1,4 + CALL LCUT_V(Q(0),I,WL(2)) + CALL VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL VVV1LP0_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) + CALL FFV1L_2(W(WE(3),H),WL(4),LC(3),ML(5),ZERO,WL(5)) + CALL FFV1LP0_3(WL(5),W(WE(4),H),LC(4),ML(6),ZERO,WL(6)) + BUFF(I)=WL(6)%W(I) + ENDDO + CALL CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.10) THEN +C Loop diagram number 16 (might be others, just an example) + DO I=1,4 + CALL LCUT_V(Q(0),I,WL(2)) + CALL VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL VVV1LP0_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) + CALL FFV1L_1(W(WE(3),H),WL(4),LC(3),ML(5),ZERO,WL(5)) + CALL FFV1LP0_3(W(WE(4),H),WL(5),LC(4),ML(6),ZERO,WL(6)) + BUFF(I)=WL(6)%W(I) + ENDDO + CALL CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.11) THEN +C Loop diagram number 17 (might be others, just an example) + DO I=1,4 + CALL LCUT_V(Q(0),I,WL(2)) + CALL VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL VVV1LP0_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) + CALL VVV1LP0_1(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) + BUFF(I)=WL(5)%W(I) + ENDDO + CALL CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.12) THEN +C Loop diagram number 18 (might be others, just an example) + DO I=1,4 + CALL LCUT_V(Q(0),I,WL(2)) + CALL VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL VVVV1LP0_1(WL(3),W(WE(2),H),W(WE(3),H),LC(2),ML(4),ZERO + $ ,WL(4)) + BUFF(I)=WL(4)%W(I) + ENDDO + CALL CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.13) THEN +C Loop diagram number 18 (might be others, just an example) + DO I=1,4 + CALL LCUT_V(Q(0),I,WL(2)) + CALL VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL VVVV3LP0_1(WL(3),W(WE(2),H),W(WE(3),H),LC(2),ML(4),ZERO + $ ,WL(4)) + BUFF(I)=WL(4)%W(I) + ENDDO + CALL CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.14) THEN +C Loop diagram number 18 (might be others, just an example) + DO I=1,4 + CALL LCUT_V(Q(0),I,WL(2)) + CALL VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL VVVV4LP0_1(WL(3),W(WE(2),H),W(WE(3),H),LC(2),ML(4),ZERO + $ ,WL(4)) + BUFF(I)=WL(4)%W(I) + ENDDO + CALL CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.15) THEN +C Loop diagram number 19 (might be others, just an example) + DO I=1,4 + CALL LCUT_V(Q(0),I,WL(2)) + CALL VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL FFV1L_1(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) + CALL FFV1L_1(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) + CALL FFV1LP0_3(W(WE(4),H),WL(5),LC(4),ML(6),ZERO,WL(6)) + BUFF(I)=WL(6)%W(I) + ENDDO + CALL CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.16) THEN +C Loop diagram number 23 (might be others, just an example) + DO I=1,4 + CALL LCUT_AF(Q(0),I,WL(2)) + CALL FFV1L_2(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL FFV1LP0_3(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) + CALL VVV1LP0_1(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) + CALL FFV1L_2(W(WE(4),H),WL(5),LC(4),ML(6),ZERO,WL(6)) + BUFF(I)=WL(6)%W(I) + ENDDO + CALL CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.17) THEN +C Loop diagram number 24 (might be others, just an example) + DO I=1,4 + CALL LCUT_F(Q(0),I,WL(2)) + CALL FFV1L_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL FFV1L_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) + CALL FFV1LP0_3(W(WE(3),H),WL(4),LC(3),ML(5),ZERO,WL(5)) + CALL FFV1L_1(W(WE(4),H),WL(5),LC(4),ML(6),ZERO,WL(6)) + BUFF(I)=WL(6)%W(I) + ENDDO + CALL CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.18) THEN +C Loop diagram number 25 (might be others, just an example) + DO I=1,4 + CALL LCUT_AF(Q(0),I,WL(2)) + CALL FFV1L_2(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL FFV1L_2(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) + CALL FFV1LP0_3(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) + CALL FFV1L_2(W(WE(4),H),WL(5),LC(4),ML(6),ZERO,WL(6)) + BUFF(I)=WL(6)%W(I) + ENDDO + CALL CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.19) THEN +C Loop diagram number 26 (might be others, just an example) + DO I=1,4 + CALL LCUT_V(Q(0),I,WL(2)) + CALL VVVV1LP0_1(WL(2),W(WE(1),H),W(WE(2),H),LC(1),ML(3),ZERO + $ ,WL(3)) + CALL VVV1LP0_1(WL(3),W(WE(3),H),LC(2),ML(4),ZERO,WL(4)) + BUFF(I)=WL(4)%W(I) + ENDDO + CALL CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.20) THEN +C Loop diagram number 26 (might be others, just an example) + DO I=1,4 + CALL LCUT_V(Q(0),I,WL(2)) + CALL VVVV3LP0_1(WL(2),W(WE(1),H),W(WE(2),H),LC(1),ML(3),ZERO + $ ,WL(3)) + CALL VVV1LP0_1(WL(3),W(WE(3),H),LC(2),ML(4),ZERO,WL(4)) + BUFF(I)=WL(4)%W(I) + ENDDO + CALL CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.21) THEN +C Loop diagram number 26 (might be others, just an example) + DO I=1,4 + CALL LCUT_V(Q(0),I,WL(2)) + CALL VVVV4LP0_1(WL(2),W(WE(1),H),W(WE(2),H),LC(1),ML(3),ZERO + $ ,WL(3)) + CALL VVV1LP0_1(WL(3),W(WE(3),H),LC(2),ML(4),ZERO,WL(4)) + BUFF(I)=WL(4)%W(I) + ENDDO + CALL CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.22) THEN +C Loop diagram number 27 (might be others, just an example) + DO I=1,4 + CALL LCUT_V(Q(0),I,WL(2)) + CALL FFV1L_1(W(WE(1),H),WL(2),LC(1),ML(3),ZERO,WL(3)) + CALL FFV1LP0_3(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) + CALL VVVV1LP0_1(WL(4),W(WE(3),H),W(WE(4),H),LC(3),ML(5),ZERO + $ ,WL(5)) + BUFF(I)=WL(5)%W(I) + ENDDO + CALL CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.23) THEN +C Loop diagram number 27 (might be others, just an example) + DO I=1,4 + CALL LCUT_V(Q(0),I,WL(2)) + CALL FFV1L_1(W(WE(1),H),WL(2),LC(1),ML(3),ZERO,WL(3)) + CALL FFV1LP0_3(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) + CALL VVVV3LP0_1(WL(4),W(WE(3),H),W(WE(4),H),LC(3),ML(5),ZERO + $ ,WL(5)) + BUFF(I)=WL(5)%W(I) + ENDDO + CALL CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.24) THEN +C Loop diagram number 27 (might be others, just an example) + DO I=1,4 + CALL LCUT_V(Q(0),I,WL(2)) + CALL FFV1L_1(W(WE(1),H),WL(2),LC(1),ML(3),ZERO,WL(3)) + CALL FFV1LP0_3(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) + CALL VVVV4LP0_1(WL(4),W(WE(3),H),W(WE(4),H),LC(3),ML(5),ZERO + $ ,WL(5)) + BUFF(I)=WL(5)%W(I) + ENDDO + CALL CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.25) THEN +C Loop diagram number 28 (might be others, just an example) + DO I=1,1 + CALL LCUT_S(Q(0),I,WL(2)) + CALL GHGHGL_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL GHGHGL_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) + BUFF(I)=WL(4)%W(I) + ENDDO + CALL CLOSE_1(BUFF(1),RES) + ELSEIF (ID.EQ.26) THEN +C Loop diagram number 29 (might be others, just an example) + DO I=1,1 + CALL LCUT_AS(Q(0),I,WL(2)) + CALL GHGHGL_2(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL GHGHGL_2(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) + CALL GHGHGL_2(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) + BUFF(I)=WL(5)%W(I) + ENDDO + CALL CLOSE_1(BUFF(1),RES) + ELSEIF (ID.EQ.27) THEN +C Loop diagram number 30 (might be others, just an example) + DO I=1,1 + CALL LCUT_S(Q(0),I,WL(2)) + CALL GHGHGL_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL GHGHGL_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) + CALL GHGHGL_1(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) + BUFF(I)=WL(5)%W(I) + ENDDO + CALL CLOSE_1(BUFF(1),RES) + ELSEIF (ID.EQ.28) THEN +C Loop diagram number 31 (might be others, just an example) + DO I=1,4 + CALL LCUT_F(Q(0),I,WL(2)) + CALL FFV1L_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL FFV1L_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) + BUFF(I)=WL(4)%W(I) + ENDDO + CALL CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.29) THEN +C Loop diagram number 32 (might be others, just an example) + DO I=1,4 + CALL LCUT_AF(Q(0),I,WL(2)) + CALL FFV1L_2(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL FFV1L_2(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) + CALL FFV1L_2(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) + BUFF(I)=WL(5)%W(I) + ENDDO + CALL CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.30) THEN +C Loop diagram number 33 (might be others, just an example) + DO I=1,4 + CALL LCUT_F(Q(0),I,WL(2)) + CALL FFV1L_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL FFV1L_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) + CALL FFV1L_1(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) + BUFF(I)=WL(5)%W(I) + ENDDO + CALL CLOSE_4(BUFF(1),RES) + ENDIF + END + + SUBROUTINE ML5_0_MPLOOPNUM(Q,RES) + USE ALOHA_OBJECT + INCLUDE 'cts_mprec.h' + IMPLICIT NONE +C +C CONSTANTS +C + INTEGER NCOMB + PARAMETER (NCOMB=16) + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INTEGER NBORNAMPS + PARAMETER (NBORNAMPS=3) + INTEGER NLOOPAMPS + PARAMETER (NLOOPAMPS=129) + INTEGER NWAVEFUNCS + PARAMETER (NWAVEFUNCS=10) + INTEGER MAXLCOUPLINGS + PARAMETER (MAXLCOUPLINGS=4) + COMPLEX*32 IMAG1 + PARAMETER (IMAG1=(0E0_16,1E0_16)) +C +C ARGUMENTS +C + INCLUDE 'cts_mpc.h' + $ , INTENT(IN), DIMENSION(0:3) :: Q + INCLUDE 'cts_mpc.h' + $ , INTENT(OUT) :: RES +C +C LOCAL VARIABLES +C + COMPLEX*32 QPRES + COMPLEX*32 QPQ(0:3) + REAL*16 QPP(0:3,NEXTERNAL) + INTEGER I,J,H + COMPLEX*32 CFTOT + COMPLEX*32 BUFF +C +C GLOBAL VARIABLES +C + LOGICAL MP_DONE + COMMON/ML5_0_MP_DONE/MP_DONE + + REAL*16 MP_PS(0:3,NEXTERNAL),MP_P(0:3,NEXTERNAL) + COMMON/ML5_0_MP_PSPOINT/MP_PS,MP_P + + REAL*8 LSCALE + INTEGER CTMODE + COMMON/ML5_0_CT/LSCALE,CTMODE + + INTEGER WE(NEXTERNAL) + INTEGER ID, SYMFACT,MULTIPLIER,AMPLNUM + COMMON/ML5_0_LOOP/WE,ID,SYMFACT,MULTIPLIER,AMPLNUM + + LOGICAL GOODHEL(NCOMB) + LOGICAL GOODAMP(NLOOPAMPS,NCOMB) + COMMON/ML5_0_FILTERS/GOODAMP,GOODHEL + + INTEGER NTRY + LOGICAL CHECKPHASE,HELDOUBLECHECKED + REAL*8 REF + COMMON/ML5_0_INIT/NTRY,CHECKPHASE,HELDOUBLECHECKED,REF + + INTEGER CF_D(NLOOPAMPS,NBORNAMPS) + INTEGER CF_N(NLOOPAMPS,NBORNAMPS) + COMMON/ML5_0_CF/CF_D,CF_N + + COMPLEX*32 AMP(NBORNAMPS,NCOMB) + COMMON/ML5_0_MP_AMPS/AMP + TYPE(MP_ALOHA) W(NWAVEFUNCS,NCOMB) + COMMON/ML5_0_MP_WFS/W + + INTEGER HELPICKED + COMMON/ML5_0_HELCHOICE/HELPICKED +C ---------- +C BEGIN CODE +C ---------- + DO I=0,3 + QPQ(I) = Q(I) + ENDDO + QPRES=(0.0E0_16,0.0E0_16) + + IF(.NOT.MP_DONE.AND.CTMODE.EQ.0) THEN +C This is just to compute the wfs in quad prec + CALL ML5_0_MP_BORN_AMPS_AND_WFS(MP_P) + MP_DONE=.TRUE. + ENDIF + + DO H=1,NCOMB + IF (((HELPICKED.EQ.-1).OR.(HELPICKED.EQ.H)) + $ .AND.((CHECKPHASE.OR..NOT.HELDOUBLECHECKED).OR.(GOODHEL(H) + $ .AND.GOODAMP(AMPLNUM,H)))) THEN + CALL ML5_0_MPLOOPNUMHEL(-QPQ,BUFF,H) + DO I=1,NBORNAMPS + CFTOT=CMPLX(CF_N(AMPLNUM,I)/(1.0E0_16*ABS(CF_D(AMPLNUM,I))) + $ ,0.0E0_16,KIND=16) + IF(CF_D(AMPLNUM,I).LT.0) CFTOT=CFTOT*IMAG1 + QPRES=QPRES+CFTOT*BUFF*CONJG(AMP(I,H)) + ENDDO + ENDIF + ENDDO + QPRES=(QPRES*MULTIPLIER)/SYMFACT + + RES=QPRES + END + + SUBROUTINE ML5_0_MPLOOPNUMHEL(Q,RES,H) + USE ALOHA_OBJECT +C +C CONSTANTS +C + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INTEGER MAXLCOUPLINGS + PARAMETER (MAXLCOUPLINGS=4) + INTEGER NMAXLOOPWFS + PARAMETER (NMAXLOOPWFS=(NEXTERNAL+2)) + REAL*16 ZERO + PARAMETER (ZERO=0E0_16) + INTEGER NWAVEFUNCS + PARAMETER (NWAVEFUNCS=10) + INTEGER NBORNAMPS + PARAMETER (NBORNAMPS=3) + INTEGER NLOOPAMPS + PARAMETER (NLOOPAMPS=129) + INTEGER NCOMB + PARAMETER (NCOMB=16) +C +C ARGUMENTS +C + COMPLEX*32 Q(0:3) + COMPLEX*32 RES + INTEGER H +C +C LOCAL VARIABLES +C + COMPLEX*32 BUFF(4) + TYPE(MP_ALOHA) WL(NMAXLOOPWFS) + INTEGER I +C +C GLOBAL VARIABLES +C + COMPLEX*32 LC(MAXLCOUPLINGS) + COMPLEX*32 ML(NEXTERNAL+2) + COMMON/ML5_0_MP_LOOP/LC,ML + + INTEGER WE(NEXTERNAL) + INTEGER ID, SYMFACT,MULTIPLIER,AMPLNUM + COMMON/ML5_0_LOOP/WE,ID,SYMFACT,MULTIPLIER,AMPLNUM + + COMPLEX*32 AMP(NBORNAMPS,NCOMB) + COMMON/ML5_0_MP_AMPS/AMP + TYPE(MP_ALOHA) W(NWAVEFUNCS,NCOMB) + COMMON/ML5_0_MP_WFS/W +C ---------- +C BEGIN CODE +C ---------- + RES=(0E0_16,0E0_16) + IF (ID.EQ.1) THEN +C Loop diagram number 4 (might be others, just an example) + DO I=1,4 + CALL MP_LCUT_V(Q(0),I,WL(2)) + CALL MP_VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL MP_VVV1LP0_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) + BUFF(I)=WL(4)%W(I) + ENDDO + CALL MP_CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.2) THEN +C Loop diagram number 5 (might be others, just an example) + DO I=1,4 + CALL MP_LCUT_V(Q(0),I,WL(2)) + CALL MP_FFV1L_1(W(WE(1),H),WL(2),LC(1),ML(3),ZERO,WL(3)) + CALL MP_FFV1LP0_3(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) + CALL MP_VVV1LP0_1(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) + BUFF(I)=WL(5)%W(I) + ENDDO + CALL MP_CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.3) THEN +C Loop diagram number 6 (might be others, just an example) + DO I=1,4 + CALL MP_LCUT_AF(Q(0),I,WL(2)) + CALL MP_FFV1LP0_3(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL MP_FFV1L_2(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) + CALL MP_FFV1L_2(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) + BUFF(I)=WL(5)%W(I) + ENDDO + CALL MP_CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.4) THEN +C Loop diagram number 7 (might be others, just an example) + DO I=1,4 + CALL MP_LCUT_AF(Q(0),I,WL(2)) + CALL MP_FFV1LP0_3(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL MP_FFV1L_2(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) + BUFF(I)=WL(4)%W(I) + ENDDO + CALL MP_CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.5) THEN +C Loop diagram number 8 (might be others, just an example) + DO I=1,4 + CALL MP_LCUT_V(Q(0),I,WL(2)) + CALL MP_VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL MP_FFV1L_2(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) + CALL MP_FFV1LP0_3(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) + BUFF(I)=WL(5)%W(I) + ENDDO + CALL MP_CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.6) THEN +C Loop diagram number 9 (might be others, just an example) + DO I=1,4 + CALL MP_LCUT_F(Q(0),I,WL(2)) + CALL MP_FFV1L_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL MP_FFV1LP0_3(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) + CALL MP_FFV1L_1(W(WE(3),H),WL(4),LC(3),ML(5),ZERO,WL(5)) + BUFF(I)=WL(5)%W(I) + ENDDO + CALL MP_CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.7) THEN +C Loop diagram number 11 (might be others, just an example) + DO I=1,4 + CALL MP_LCUT_V(Q(0),I,WL(2)) + CALL MP_VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL MP_FFV1L_1(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) + CALL MP_FFV1LP0_3(W(WE(3),H),WL(4),LC(3),ML(5),ZERO,WL(5)) + BUFF(I)=WL(5)%W(I) + ENDDO + CALL MP_CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.8) THEN +C Loop diagram number 12 (might be others, just an example) + DO I=1,4 + CALL MP_LCUT_AF(Q(0),I,WL(2)) + CALL MP_FFV1L_2(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL MP_FFV1LP0_3(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) + CALL MP_FFV1L_2(W(WE(3),H),WL(4),LC(3),ML(5),ZERO,WL(5)) + BUFF(I)=WL(5)%W(I) + ENDDO + CALL MP_CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.9) THEN +C Loop diagram number 15 (might be others, just an example) + DO I=1,4 + CALL MP_LCUT_V(Q(0),I,WL(2)) + CALL MP_VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL MP_VVV1LP0_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) + CALL MP_FFV1L_2(W(WE(3),H),WL(4),LC(3),ML(5),ZERO,WL(5)) + CALL MP_FFV1LP0_3(WL(5),W(WE(4),H),LC(4),ML(6),ZERO,WL(6)) + BUFF(I)=WL(6)%W(I) + ENDDO + CALL MP_CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.10) THEN +C Loop diagram number 16 (might be others, just an example) + DO I=1,4 + CALL MP_LCUT_V(Q(0),I,WL(2)) + CALL MP_VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL MP_VVV1LP0_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) + CALL MP_FFV1L_1(W(WE(3),H),WL(4),LC(3),ML(5),ZERO,WL(5)) + CALL MP_FFV1LP0_3(W(WE(4),H),WL(5),LC(4),ML(6),ZERO,WL(6)) + BUFF(I)=WL(6)%W(I) + ENDDO + CALL MP_CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.11) THEN +C Loop diagram number 17 (might be others, just an example) + DO I=1,4 + CALL MP_LCUT_V(Q(0),I,WL(2)) + CALL MP_VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL MP_VVV1LP0_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) + CALL MP_VVV1LP0_1(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) + BUFF(I)=WL(5)%W(I) + ENDDO + CALL MP_CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.12) THEN +C Loop diagram number 18 (might be others, just an example) + DO I=1,4 + CALL MP_LCUT_V(Q(0),I,WL(2)) + CALL MP_VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL MP_VVVV1LP0_1(WL(3),W(WE(2),H),W(WE(3),H),LC(2),ML(4) + $ ,ZERO,WL(4)) + BUFF(I)=WL(4)%W(I) + ENDDO + CALL MP_CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.13) THEN +C Loop diagram number 18 (might be others, just an example) + DO I=1,4 + CALL MP_LCUT_V(Q(0),I,WL(2)) + CALL MP_VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL MP_VVVV3LP0_1(WL(3),W(WE(2),H),W(WE(3),H),LC(2),ML(4) + $ ,ZERO,WL(4)) + BUFF(I)=WL(4)%W(I) + ENDDO + CALL MP_CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.14) THEN +C Loop diagram number 18 (might be others, just an example) + DO I=1,4 + CALL MP_LCUT_V(Q(0),I,WL(2)) + CALL MP_VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL MP_VVVV4LP0_1(WL(3),W(WE(2),H),W(WE(3),H),LC(2),ML(4) + $ ,ZERO,WL(4)) + BUFF(I)=WL(4)%W(I) + ENDDO + CALL MP_CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.15) THEN +C Loop diagram number 19 (might be others, just an example) + DO I=1,4 + CALL MP_LCUT_V(Q(0),I,WL(2)) + CALL MP_VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL MP_FFV1L_1(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) + CALL MP_FFV1L_1(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) + CALL MP_FFV1LP0_3(W(WE(4),H),WL(5),LC(4),ML(6),ZERO,WL(6)) + BUFF(I)=WL(6)%W(I) + ENDDO + CALL MP_CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.16) THEN +C Loop diagram number 23 (might be others, just an example) + DO I=1,4 + CALL MP_LCUT_AF(Q(0),I,WL(2)) + CALL MP_FFV1L_2(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL MP_FFV1LP0_3(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) + CALL MP_VVV1LP0_1(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) + CALL MP_FFV1L_2(W(WE(4),H),WL(5),LC(4),ML(6),ZERO,WL(6)) + BUFF(I)=WL(6)%W(I) + ENDDO + CALL MP_CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.17) THEN +C Loop diagram number 24 (might be others, just an example) + DO I=1,4 + CALL MP_LCUT_F(Q(0),I,WL(2)) + CALL MP_FFV1L_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL MP_FFV1L_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) + CALL MP_FFV1LP0_3(W(WE(3),H),WL(4),LC(3),ML(5),ZERO,WL(5)) + CALL MP_FFV1L_1(W(WE(4),H),WL(5),LC(4),ML(6),ZERO,WL(6)) + BUFF(I)=WL(6)%W(I) + ENDDO + CALL MP_CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.18) THEN +C Loop diagram number 25 (might be others, just an example) + DO I=1,4 + CALL MP_LCUT_AF(Q(0),I,WL(2)) + CALL MP_FFV1L_2(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL MP_FFV1L_2(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) + CALL MP_FFV1LP0_3(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) + CALL MP_FFV1L_2(W(WE(4),H),WL(5),LC(4),ML(6),ZERO,WL(6)) + BUFF(I)=WL(6)%W(I) + ENDDO + CALL MP_CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.19) THEN +C Loop diagram number 26 (might be others, just an example) + DO I=1,4 + CALL MP_LCUT_V(Q(0),I,WL(2)) + CALL MP_VVVV1LP0_1(WL(2),W(WE(1),H),W(WE(2),H),LC(1),ML(3) + $ ,ZERO,WL(3)) + CALL MP_VVV1LP0_1(WL(3),W(WE(3),H),LC(2),ML(4),ZERO,WL(4)) + BUFF(I)=WL(4)%W(I) + ENDDO + CALL MP_CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.20) THEN +C Loop diagram number 26 (might be others, just an example) + DO I=1,4 + CALL MP_LCUT_V(Q(0),I,WL(2)) + CALL MP_VVVV3LP0_1(WL(2),W(WE(1),H),W(WE(2),H),LC(1),ML(3) + $ ,ZERO,WL(3)) + CALL MP_VVV1LP0_1(WL(3),W(WE(3),H),LC(2),ML(4),ZERO,WL(4)) + BUFF(I)=WL(4)%W(I) + ENDDO + CALL MP_CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.21) THEN +C Loop diagram number 26 (might be others, just an example) + DO I=1,4 + CALL MP_LCUT_V(Q(0),I,WL(2)) + CALL MP_VVVV4LP0_1(WL(2),W(WE(1),H),W(WE(2),H),LC(1),ML(3) + $ ,ZERO,WL(3)) + CALL MP_VVV1LP0_1(WL(3),W(WE(3),H),LC(2),ML(4),ZERO,WL(4)) + BUFF(I)=WL(4)%W(I) + ENDDO + CALL MP_CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.22) THEN +C Loop diagram number 27 (might be others, just an example) + DO I=1,4 + CALL MP_LCUT_V(Q(0),I,WL(2)) + CALL MP_FFV1L_1(W(WE(1),H),WL(2),LC(1),ML(3),ZERO,WL(3)) + CALL MP_FFV1LP0_3(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) + CALL MP_VVVV1LP0_1(WL(4),W(WE(3),H),W(WE(4),H),LC(3),ML(5) + $ ,ZERO,WL(5)) + BUFF(I)=WL(5)%W(I) + ENDDO + CALL MP_CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.23) THEN +C Loop diagram number 27 (might be others, just an example) + DO I=1,4 + CALL MP_LCUT_V(Q(0),I,WL(2)) + CALL MP_FFV1L_1(W(WE(1),H),WL(2),LC(1),ML(3),ZERO,WL(3)) + CALL MP_FFV1LP0_3(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) + CALL MP_VVVV3LP0_1(WL(4),W(WE(3),H),W(WE(4),H),LC(3),ML(5) + $ ,ZERO,WL(5)) + BUFF(I)=WL(5)%W(I) + ENDDO + CALL MP_CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.24) THEN +C Loop diagram number 27 (might be others, just an example) + DO I=1,4 + CALL MP_LCUT_V(Q(0),I,WL(2)) + CALL MP_FFV1L_1(W(WE(1),H),WL(2),LC(1),ML(3),ZERO,WL(3)) + CALL MP_FFV1LP0_3(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) + CALL MP_VVVV4LP0_1(WL(4),W(WE(3),H),W(WE(4),H),LC(3),ML(5) + $ ,ZERO,WL(5)) + BUFF(I)=WL(5)%W(I) + ENDDO + CALL MP_CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.25) THEN +C Loop diagram number 28 (might be others, just an example) + DO I=1,1 + CALL MP_LCUT_S(Q(0),I,WL(2)) + CALL MP_GHGHGL_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL MP_GHGHGL_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) + BUFF(I)=WL(4)%W(I) + ENDDO + CALL MP_CLOSE_1(BUFF(1),RES) + ELSEIF (ID.EQ.26) THEN +C Loop diagram number 29 (might be others, just an example) + DO I=1,1 + CALL MP_LCUT_AS(Q(0),I,WL(2)) + CALL MP_GHGHGL_2(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL MP_GHGHGL_2(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) + CALL MP_GHGHGL_2(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) + BUFF(I)=WL(5)%W(I) + ENDDO + CALL MP_CLOSE_1(BUFF(1),RES) + ELSEIF (ID.EQ.27) THEN +C Loop diagram number 30 (might be others, just an example) + DO I=1,1 + CALL MP_LCUT_S(Q(0),I,WL(2)) + CALL MP_GHGHGL_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL MP_GHGHGL_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) + CALL MP_GHGHGL_1(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) + BUFF(I)=WL(5)%W(I) + ENDDO + CALL MP_CLOSE_1(BUFF(1),RES) + ELSEIF (ID.EQ.28) THEN +C Loop diagram number 31 (might be others, just an example) + DO I=1,4 + CALL MP_LCUT_F(Q(0),I,WL(2)) + CALL MP_FFV1L_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL MP_FFV1L_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) + BUFF(I)=WL(4)%W(I) + ENDDO + CALL MP_CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.29) THEN +C Loop diagram number 32 (might be others, just an example) + DO I=1,4 + CALL MP_LCUT_AF(Q(0),I,WL(2)) + CALL MP_FFV1L_2(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL MP_FFV1L_2(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) + CALL MP_FFV1L_2(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) + BUFF(I)=WL(5)%W(I) + ENDDO + CALL MP_CLOSE_4(BUFF(1),RES) + ELSEIF (ID.EQ.30) THEN +C Loop diagram number 33 (might be others, just an example) + DO I=1,4 + CALL MP_LCUT_F(Q(0),I,WL(2)) + CALL MP_FFV1L_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) + CALL MP_FFV1L_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) + CALL MP_FFV1L_1(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) + BUFF(I)=WL(5)%W(I) + ENDDO + CALL MP_CLOSE_4(BUFF(1),RES) + ENDIF + END + + SUBROUTINE ML5_0_MPLOOPNUM_DUMMY(Q,RES) +C +C ARGUMENTS +C + INCLUDE 'cts_mprec.h' + INCLUDE 'cts_mpc.h' + $ , INTENT(IN), DIMENSION(0:3) :: Q + INCLUDE 'cts_mpc.h' + $ , INTENT(OUT) :: RES +C +C LOCAL VARIABLES +C + COMPLEX*16 DRES + COMPLEX*16 DQ(0:3) + INTEGER I +C ---------- +C BEGIN CODE +C ---------- + DO I=0,3 + DQ(I) = Q(I) + ENDDO + + CALL ML5_0_LOOPNUM(DQ,DRES) + RES=DRES + + END + diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/makefile b/UNITTEST_proc/SubProcesses/P0_gg_ttx/makefile new file mode 120000 index 0000000000..cc63b08c84 --- /dev/null +++ b/UNITTEST_proc/SubProcesses/P0_gg_ttx/makefile @@ -0,0 +1 @@ +../makefile \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/mg5_citation.f b/UNITTEST_proc/SubProcesses/P0_gg_ttx/mg5_citation.f new file mode 120000 index 0000000000..dad07bbaa4 --- /dev/null +++ b/UNITTEST_proc/SubProcesses/P0_gg_ttx/mg5_citation.f @@ -0,0 +1 @@ +../mg5_citation.f \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/mp_born_amps_and_wfs.f b/UNITTEST_proc/SubProcesses/P0_gg_ttx/mp_born_amps_and_wfs.f new file mode 100644 index 0000000000..7a036ee3d5 --- /dev/null +++ b/UNITTEST_proc/SubProcesses/P0_gg_ttx/mp_born_amps_and_wfs.f @@ -0,0 +1,282 @@ + SUBROUTINE ML5_0_MP_BORN_AMPS_AND_WFS(P) + USE ALOHA_OBJECT +C +C Generated by MadGraph5_aMC@NLO v. 3.7.2, 2026-04-29 +C By the MadGraph5_aMC@NLO Development Team +C Visit launchpad.net/madgraph5 and amcatnlo.web.cern.ch +C +C Computes all the AMP and WFS in quadruple precision for the +C phase space point P(0:3,NEXTERNAL) +C +C Process: g g > t t~ QCD<=2 QED=0 [ virt = QCD ] +C + IMPLICIT NONE +C +C CONSTANTS +C + INTEGER NBORNAMPS + PARAMETER (NBORNAMPS=3) + INTEGER NLOOPAMPS, NCTAMPS + PARAMETER (NLOOPAMPS=129, NCTAMPS=85) + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INTEGER NWAVEFUNCS + PARAMETER (NWAVEFUNCS=10) + INTEGER NCOMB + PARAMETER (NCOMB=16) + REAL*16 ZERO + PARAMETER (ZERO=0E0_16) + COMPLEX*32 IMAG1 + PARAMETER (IMAG1=(0E0_16,1E0_16)) + +C +C ARGUMENTS +C + REAL*16 P(0:3,NEXTERNAL) +C +C LOCAL VARIABLES +C + INTEGER I,J,H + INTEGER NHEL(NEXTERNAL), IC(NEXTERNAL) + DATA IC/NEXTERNAL*1/ + INTEGER FLAVOR(NEXTERNAL) + DATA FLAVOR /NEXTERNAL*1/ +C +C FUNCTIONS +C + LOGICAL ML5_0_IS_HEL_SELECTED +C +C GLOBAL VARIABLES +C + INCLUDE 'mp_coupl_same_name.inc' + + INTEGER NTRY + LOGICAL CHECKPHASE,HELDOUBLECHECKED + REAL*8 REF + COMMON/ML5_0_INIT/NTRY,CHECKPHASE,HELDOUBLECHECKED,REF + + LOGICAL GOODHEL(NCOMB) + LOGICAL GOODAMP(NLOOPAMPS,NCOMB) + COMMON/ML5_0_FILTERS/GOODAMP,GOODHEL + + INTEGER HELPICKED + COMMON/ML5_0_HELCHOICE/HELPICKED + + COMPLEX*32 AMP(NBORNAMPS,NCOMB) + COMMON/ML5_0_MP_AMPS/AMP + COMPLEX*16 DPAMP(NBORNAMPS,NCOMB) + COMMON/ML5_0_AMPS/DPAMP + TYPE(MP_ALOHA) W(NWAVEFUNCS,NCOMB) + COMMON/ML5_0_MP_WFS/W + + COMPLEX*32 AMPL(3,NCTAMPS) + COMMON/ML5_0_MP_AMPL/AMPL + + TYPE(ALOHA) DPW(NWAVEFUNCS,NCOMB) + COMMON/ML5_0_WFCTS/DPW + + COMPLEX*16 DPAMPL(3,NLOOPAMPS) + LOGICAL S(NLOOPAMPS) + COMMON/ML5_0_AMPL/DPAMPL,S + + INTEGER HELC(NEXTERNAL,NCOMB) + COMMON/ML5_0_HELCONFIGS/HELC + + LOGICAL MP_DONE_ONCE + COMMON/ML5_0_MP_DONE_ONCE/MP_DONE_ONCE + +C This array specify potential special requirements on the +C helicities to +C consider. POLARIZATIONS(0,0) is -1 if there is not such +C requirement. + INTEGER POLARIZATIONS(0:NEXTERNAL,0:5) + COMMON/ML5_0_BEAM_POL/POLARIZATIONS + +C ---------- +C BEGIN CODE +C --------- + + MP_DONE_ONCE=.TRUE. + +C To be on the safe side, we always update the MP params here. +C It can be redundant as this routine can be called a couple of +C times for the same PS point during the stability checks. +C But it is really not time consuming and I would rather be safe. + CALL MP_UPDATE_AS_PARAM() + + DO H=1,NCOMB + IF ((HELPICKED.EQ.H).OR.((HELPICKED.EQ.-1) + $ .AND.((CHECKPHASE.OR..NOT.HELDOUBLECHECKED).OR.GOODHEL(H)))) + $ THEN +C Handle the possible requirement of specific polarizations + IF ((.NOT.CHECKPHASE) + $ .AND.HELDOUBLECHECKED.AND.POLARIZATIONS(0,0) + $ .EQ.0.AND.(.NOT.ML5_0_IS_HEL_SELECTED(H))) THEN + CYCLE + ENDIF + DO I=1,NEXTERNAL + NHEL(I)=HELC(I,H) + ENDDO + CALL MP_VXXXXX(P(0,1),ZERO,NHEL(1),-1,W(1,H)) + CALL MP_VXXXXX(P(0,2),ZERO,NHEL(2),-1,W(2,H)) + CALL MP_OXXXXX(P(0,3),MDL_MT,NHEL(3),+1, FLAVOR(3),W(3,H)) + CALL MP_IXXXXX(P(0,4),MDL_MT,NHEL(4),-1, FLAVOR(4),W(4,H)) + CALL MP_VVV1P0_1(W(1,H),W(2,H),GC_4,ZERO,ZERO,W(5,H)) +C Amplitude(s) for born diagram with ID 1 + CALL MP_FFV1_0(W(4,H),W(3,H),W(5,H),GC_5,AMP(1,H)) + CALL MP_FFV1_1(W(3,H),W(1,H),GC_5,MDL_MT,MDL_WT,W(6,H)) +C Amplitude(s) for born diagram with ID 2 + CALL MP_FFV1_0(W(4,H),W(6,H),W(2,H),GC_5,AMP(2,H)) + CALL MP_FFV1_2(W(4,H),W(1,H),GC_5,MDL_MT,MDL_WT,W(7,H)) +C Amplitude(s) for born diagram with ID 3 + CALL MP_FFV1_0(W(7,H),W(3,H),W(2,H),GC_5,AMP(3,H)) + CALL MP_FFV1P0_3(W(4,H),W(3,H),GC_5,ZERO,ZERO,W(8,H)) +C Counter-term amplitude(s) for loop diagram number 4 + CALL MP_R2_GG_1_R2_GG_2_0(W(5,H),W(8,H),R2_GGG_1,R2_GGG_2 + $ ,AMPL(1,1)) +C Counter-term amplitude(s) for loop diagram number 5 + CALL MP_FFV1_0(W(4,H),W(3,H),W(5,H),R2_GQQ,AMPL(1,2)) + CALL MP_FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQB_1EPS,AMPL(2,3)) + CALL MP_FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQB_1EPS,AMPL(2,4)) + CALL MP_FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQB_1EPS,AMPL(2,5)) + CALL MP_FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQB_1EPS,AMPL(2,6)) + CALL MP_FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQB_1EPS,AMPL(2,7)) + CALL MP_FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQB_1EPS,AMPL(2,8)) + CALL MP_FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQG_1EPS,AMPL(2,9)) + CALL MP_FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQB,AMPL(1,10)) + CALL MP_FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQT,AMPL(1,11)) + CALL MP_FFV1_2(W(4,H),W(2,H),GC_5,MDL_MT,MDL_WT,W(9,H)) +C Counter-term amplitude(s) for loop diagram number 7 + CALL MP_R2_QQ_1_R2_QQ_2_0(W(9,H),W(6,H),R2_QQQ,R2_QQT,AMPL(1 + $ ,12)) + CALL MP_R2_QQ_2_0(W(9,H),W(6,H),UV_TMASS_1EPS,AMPL(2,13)) + CALL MP_R2_QQ_2_0(W(9,H),W(6,H),UV_TMASS,AMPL(1,14)) +C Counter-term amplitude(s) for loop diagram number 8 + CALL MP_FFV1_0(W(4,H),W(6,H),W(2,H),R2_GQQ,AMPL(1,15)) + CALL MP_FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQB_1EPS,AMPL(2,16)) + CALL MP_FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQB_1EPS,AMPL(2,17)) + CALL MP_FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQB_1EPS,AMPL(2,18)) + CALL MP_FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQB_1EPS,AMPL(2,19)) + CALL MP_FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQB_1EPS,AMPL(2,20)) + CALL MP_FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQB_1EPS,AMPL(2,21)) + CALL MP_FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQG_1EPS,AMPL(2,22)) + CALL MP_FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQB,AMPL(1,23)) + CALL MP_FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQT,AMPL(1,24)) + CALL MP_FFV1_1(W(3,H),W(2,H),GC_5,MDL_MT,MDL_WT,W(10,H)) +C Counter-term amplitude(s) for loop diagram number 10 + CALL MP_R2_QQ_1_R2_QQ_2_0(W(7,H),W(10,H),R2_QQQ,R2_QQT + $ ,AMPL(1,25)) + CALL MP_R2_QQ_2_0(W(7,H),W(10,H),UV_TMASS_1EPS,AMPL(2,26)) + CALL MP_R2_QQ_2_0(W(7,H),W(10,H),UV_TMASS,AMPL(1,27)) +C Counter-term amplitude(s) for loop diagram number 11 + CALL MP_FFV1_0(W(7,H),W(3,H),W(2,H),R2_GQQ,AMPL(1,28)) + CALL MP_FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQB_1EPS,AMPL(2,29)) + CALL MP_FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQB_1EPS,AMPL(2,30)) + CALL MP_FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQB_1EPS,AMPL(2,31)) + CALL MP_FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQB_1EPS,AMPL(2,32)) + CALL MP_FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQB_1EPS,AMPL(2,33)) + CALL MP_FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQB_1EPS,AMPL(2,34)) + CALL MP_FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQG_1EPS,AMPL(2,35)) + CALL MP_FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQB,AMPL(1,36)) + CALL MP_FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQT,AMPL(1,37)) +C Counter-term amplitude(s) for loop diagram number 13 + CALL MP_FFV1_0(W(4,H),W(10,H),W(1,H),R2_GQQ,AMPL(1,38)) + CALL MP_FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQB_1EPS,AMPL(2,39)) + CALL MP_FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQB_1EPS,AMPL(2,40)) + CALL MP_FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQB_1EPS,AMPL(2,41)) + CALL MP_FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQB_1EPS,AMPL(2,42)) + CALL MP_FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQB_1EPS,AMPL(2,43)) + CALL MP_FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQB_1EPS,AMPL(2,44)) + CALL MP_FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQG_1EPS,AMPL(2,45)) + CALL MP_FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQB,AMPL(1,46)) + CALL MP_FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQT,AMPL(1,47)) +C Counter-term amplitude(s) for loop diagram number 14 + CALL MP_FFV1_0(W(9,H),W(3,H),W(1,H),R2_GQQ,AMPL(1,48)) + CALL MP_FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQB_1EPS,AMPL(2,49)) + CALL MP_FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQB_1EPS,AMPL(2,50)) + CALL MP_FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQB_1EPS,AMPL(2,51)) + CALL MP_FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQB_1EPS,AMPL(2,52)) + CALL MP_FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQB_1EPS,AMPL(2,53)) + CALL MP_FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQB_1EPS,AMPL(2,54)) + CALL MP_FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQG_1EPS,AMPL(2,55)) + CALL MP_FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQB,AMPL(1,56)) + CALL MP_FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQT,AMPL(1,57)) +C Counter-term amplitude(s) for loop diagram number 17 + CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),R2_3GG,AMPL(1,58)) + CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GB_1EPS,AMPL(2,59)) + CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GB_1EPS,AMPL(2,60)) + CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GB_1EPS,AMPL(2,61)) + CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GB_1EPS,AMPL(2,62)) + CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GB_1EPS,AMPL(2,63)) + CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GB_1EPS,AMPL(2,64)) + CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GG_1EPS,AMPL(2,65)) + CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GB,AMPL(1,66)) + CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GT,AMPL(1,67)) +C Counter-term amplitude(s) for loop diagram number 31 + CALL MP_R2_GG_1_0(W(5,H),W(8,H),R2_GGQ,AMPL(1,68)) + CALL MP_R2_GG_1_0(W(5,H),W(8,H),R2_GGQ,AMPL(1,69)) + CALL MP_R2_GG_1_0(W(5,H),W(8,H),R2_GGQ,AMPL(1,70)) + CALL MP_R2_GG_1_0(W(5,H),W(8,H),R2_GGQ,AMPL(1,71)) +C Counter-term amplitude(s) for loop diagram number 32 + CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),R2_3GQ,AMPL(1,72)) + CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),R2_3GQ,AMPL(1,73)) + CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),R2_3GQ,AMPL(1,74)) + CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),R2_3GQ,AMPL(1,75)) +C Counter-term amplitude(s) for loop diagram number 34 + CALL MP_R2_GG_1_R2_GG_3_0(W(5,H),W(8,H),R2_GGQ,R2_GGB,AMPL(1 + $ ,76)) +C Counter-term amplitude(s) for loop diagram number 35 + CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),R2_3GQ,AMPL(1,77)) +C Counter-term amplitude(s) for loop diagram number 37 + CALL MP_R2_GG_1_R2_GG_3_0(W(5,H),W(8,H),R2_GGQ,R2_GGT,AMPL(1 + $ ,78)) +C Counter-term amplitude(s) for loop diagram number 38 + CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),R2_3GQ,AMPL(1,79)) +C Amplitude(s) for UVCT diagram with ID 40 + CALL MP_FFV1_0(W(4,H),W(3,H),W(5,H),GC_5,AMPL(2,80)) + AMPL(2,80)=AMPL(2,80)*(4.0D0*UVWFCT_G_1_1EPS+2.0D0 + $ *UVWFCT_B_0_1EPS) +C Amplitude(s) for UVCT diagram with ID 41 + CALL MP_FFV1_0(W(4,H),W(3,H),W(5,H),GC_5,AMPL(1,81)) + AMPL(1,81)=AMPL(1,81)*(2.0D0*UVWFCT_G_1+2.0D0*UVWFCT_G_2 + $ +2.0D0*UVWFCT_T_0) +C Amplitude(s) for UVCT diagram with ID 42 + CALL MP_FFV1_0(W(4,H),W(6,H),W(2,H),GC_5,AMPL(2,82)) + AMPL(2,82)=AMPL(2,82)*(4.0D0*UVWFCT_G_1_1EPS+2.0D0 + $ *UVWFCT_B_0_1EPS) +C Amplitude(s) for UVCT diagram with ID 43 + CALL MP_FFV1_0(W(4,H),W(6,H),W(2,H),GC_5,AMPL(1,83)) + AMPL(1,83)=AMPL(1,83)*(2.0D0*UVWFCT_G_1+2.0D0*UVWFCT_G_2 + $ +2.0D0*UVWFCT_T_0) +C Amplitude(s) for UVCT diagram with ID 44 + CALL MP_FFV1_0(W(7,H),W(3,H),W(2,H),GC_5,AMPL(2,84)) + AMPL(2,84)=AMPL(2,84)*(4.0D0*UVWFCT_G_1_1EPS+2.0D0 + $ *UVWFCT_B_0_1EPS) +C Amplitude(s) for UVCT diagram with ID 45 + CALL MP_FFV1_0(W(7,H),W(3,H),W(2,H),GC_5,AMPL(1,85)) + AMPL(1,85)=AMPL(1,85)*(2.0D0*UVWFCT_G_1+2.0D0*UVWFCT_G_2 + $ +2.0D0*UVWFCT_T_0) +C Copy the qp wfs to the dp ones as they are used to setup the +C CT calls. + DO I=1,NWAVEFUNCS + DO J=1,SIZE(W(I,H)%W) + DPW(I,H)%W(J)=W(I,H)%W(J) + ENDDO + DPW(I,H)%P = W(I,H)%P + DPW(I,H)%FLV_INDEX = W(I,H)%FLV_INDEX + ENDDO +C Same for the counterterms amplitudes + DO I=1,NCTAMPS + DO J=1,3 + DPAMPL(J,I)=AMPL(J,I) + S(I)=.TRUE. + ENDDO + ENDDO + DO I=1,NBORNAMPS + DPAMP(I,H)=AMP(I,H) + ENDDO + ENDIF + ENDDO + + END + diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/mp_coupl.inc b/UNITTEST_proc/SubProcesses/P0_gg_ttx/mp_coupl.inc new file mode 120000 index 0000000000..bd73d507b2 --- /dev/null +++ b/UNITTEST_proc/SubProcesses/P0_gg_ttx/mp_coupl.inc @@ -0,0 +1 @@ +../mp_coupl.inc \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/mp_coupl_same_name.inc b/UNITTEST_proc/SubProcesses/P0_gg_ttx/mp_coupl_same_name.inc new file mode 120000 index 0000000000..819d1f1826 --- /dev/null +++ b/UNITTEST_proc/SubProcesses/P0_gg_ttx/mp_coupl_same_name.inc @@ -0,0 +1 @@ +../mp_coupl_same_name.inc \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/nexternal.inc b/UNITTEST_proc/SubProcesses/P0_gg_ttx/nexternal.inc new file mode 100644 index 0000000000..f50affaedb --- /dev/null +++ b/UNITTEST_proc/SubProcesses/P0_gg_ttx/nexternal.inc @@ -0,0 +1,4 @@ + INTEGER NEXTERNAL + PARAMETER (NEXTERNAL=4) + INTEGER NINCOMING + PARAMETER (NINCOMING=2) diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/ngraphs.inc b/UNITTEST_proc/SubProcesses/P0_gg_ttx/ngraphs.inc new file mode 100644 index 0000000000..f6b2b0b7ac --- /dev/null +++ b/UNITTEST_proc/SubProcesses/P0_gg_ttx/ngraphs.inc @@ -0,0 +1,2 @@ + INTEGER N_MAX_CG + PARAMETER (N_MAX_CG=176) diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/nsquaredSO.inc b/UNITTEST_proc/SubProcesses/P0_gg_ttx/nsquaredSO.inc new file mode 100644 index 0000000000..8060bbf5e8 --- /dev/null +++ b/UNITTEST_proc/SubProcesses/P0_gg_ttx/nsquaredSO.inc @@ -0,0 +1,2 @@ + INTEGER NSQUAREDSO + PARAMETER (NSQUAREDSO=0) diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/pmass.inc b/UNITTEST_proc/SubProcesses/P0_gg_ttx/pmass.inc new file mode 100644 index 0000000000..a16f00b86d --- /dev/null +++ b/UNITTEST_proc/SubProcesses/P0_gg_ttx/pmass.inc @@ -0,0 +1,4 @@ + PMASS(1)=ZERO + PMASS(2)=ZERO + PMASS(3)=ABS(MDL_MT) + PMASS(4)=ABS(MDL_MT) diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/unique_id.inc b/UNITTEST_proc/SubProcesses/P0_gg_ttx/unique_id.inc new file mode 100644 index 0000000000..534d4d1b58 --- /dev/null +++ b/UNITTEST_proc/SubProcesses/P0_gg_ttx/unique_id.inc @@ -0,0 +1,2 @@ + integer UNIQUE_ID + parameter(UNIQUE_ID=1) \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/coupl.inc b/UNITTEST_proc/SubProcesses/coupl.inc new file mode 120000 index 0000000000..06a93d2f15 --- /dev/null +++ b/UNITTEST_proc/SubProcesses/coupl.inc @@ -0,0 +1 @@ +../Source/MODEL/coupl.inc \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/cts_mpc.h b/UNITTEST_proc/SubProcesses/cts_mpc.h new file mode 100644 index 0000000000..803584d2de --- /dev/null +++ b/UNITTEST_proc/SubProcesses/cts_mpc.h @@ -0,0 +1,2 @@ + COMPLEX(KIND=16) + diff --git a/UNITTEST_proc/SubProcesses/cts_mprec.h b/UNITTEST_proc/SubProcesses/cts_mprec.h new file mode 100644 index 0000000000..39ae82ac4c --- /dev/null +++ b/UNITTEST_proc/SubProcesses/cts_mprec.h @@ -0,0 +1,2 @@ + USE MPMODULE + diff --git a/UNITTEST_proc/SubProcesses/makefile b/UNITTEST_proc/SubProcesses/makefile new file mode 100644 index 0000000000..64aeb77941 --- /dev/null +++ b/UNITTEST_proc/SubProcesses/makefile @@ -0,0 +1,201 @@ + +ifeq ($(wildcard ../Source/make_opts),) + ifeq ($(wildcard ../../Source/make_opts),) + ROOT = ../../.. + else + ROOT = ../.. + endif +else + ROOT = .. +endif +LIBDIR = $(abspath $(ROOT))/lib/ + +PROG = check +all : $(PROG) + +HERE := $(dir $(abspath $(firstword $(MAKEFILE_LIST)))) +ROOTNAME = $(notdir $(abspath $(ROOT))) + +# For the compilation of the MadLoop file polynomial.f it makes a big difference to use -O3 and +# to turn off the bounds check. These can however be modified here if really necessary. +POLYNOMIAL_OPTIMIZATION = -O3 +POLYNOMIAL_BOUNDS_CHECK = + +include $(ROOT)/Source/make_opts +FFLAGS += -I$(ROOT)/Source/MODEL -I$(ROOT)/Source/DHELAS +include $(ROOT)/SubProcesses/MadLoop_makefile_definitions +SHELL = /bin/bash + +OLP = OLP +STABCHECKDRIVER = StabilityCheckDriver +CHECK_SA_BORN_SPLITORDERS = check_sa_born_splitOrders +LINKLIBS = -L$(LIBDIR) -ldhelas -lmodel $(LINK_LOOP_LIBS) $(LDFLAGS) +LIBS = $(LIBDIR)libdhelas.$(libext) $(LIBDIR)libmodel.$(libext) $(LOOP_LIBS) +DYLIBS = $(LIBDIR)libdhelas.$(dylibext) $(LIBDIR)libmodel.$(dylibext) $(LOOP_LIBS) + +PROCESS= MadLoopParamReader.o MadLoopCommons.o \ + $(patsubst $(DOTF),$(DOTO),$(wildcard polynomial.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard loop_matrix.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard improve_ps.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard born_matrix.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard CT_interface.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard loop_num.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard helas_calls*.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard jamp?_calls_*.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard mp_born_amps_and_wfs.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard mp_compute_loop_coefs.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard mp_helas_calls*.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard coef_construction_*.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard loop_CT_calls_*.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard mp_coef_construction_*.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard TIR_interface.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard GOLEM_interface.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard COLLIER_interface.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard compute_color_flows.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard mg5_citation.f)) + +OLP_PROCESS= MadLoopParamReader.o MadLoopCommons.o \ + $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/polynomial.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/loop_matrix.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/improve_ps.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/born_matrix.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/CT_interface.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/loop_num.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/helas_calls*.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/jamp?_calls_*.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/mp_born_amps_and_wfs.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/mp_compute_loop_coefs.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/mp_helas_calls*.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/coef_construction_*.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/loop_CT_calls_*.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/mp_coef_construction_*.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/TIR_interface.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/GOLEM_interface.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/COLLIER_interface.f)) \ + $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/compute_color_flows.f)) + +POLYNOMIAL = $(patsubst $(DOTF),$(DOTO),$(wildcard polynomial.f)) +OLP_POLYNOMIAL = $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/polynomial.f)) + + + +$(PROG): check_sa.o $(PROCESS) makefile $(LIBS) libcollier.$(dylibext) + $(FC) $(FFLAGS) -o $(PROG) check_sa.o $(PROCESS) $(LINKLIBS) + +$(STABCHECKDRIVER): StabilityCheckDriver.o $(PROCESS) makefile $(LIBS) + $(FC) $(FFLAGS) -o $(STABCHECKDRIVER) StabilityCheckDriver.o $(PROCESS) $(LINKLIBS) + +# The program below is not essential but just an helpful one to run the born only +$(CHECK_SA_BORN_SPLITORDERS): check_sa_born_splitOrders.o $(patsubst $(DOTF),$(DOTO),$(wildcard *born_matrix.f)) makefile $(LIBDIR)libdhelas.$(libext) $(LIBDIR)libmodel.$(libext) + $(FC) $(FFLAGS) -o $(CHECK_SA_BORN_SPLITORDERS) check_sa_born_splitOrders.o $(patsubst $(DOTF),$(DOTO),$(wildcard *born_matrix.f)) -L$(LIBDIR) -ldhelas -lmodel + +# This is the core of madloop computationally wise, so make sure to turn optimizations on and bound checks off. +# We use %olynomial.o and not directly polynomial.o because we want it to match when both doing make check here +# or make OLP one directory above +%oloop_matrix.o : %olynomial.o %oloop_matrix.f +%olynomial.o : %olynomial.f + $(FC) $(patsubst -O%,, $(subst -fbounds-check,,$(FFLAGS))) $(POLYNOMIAL_OPTIMIZATION) $(POLYNOMIAL_BOUNDS_CHECK) -c $< -o $@ $(LOOP_INCLUDE) + +%/%oloop_matrix.o : %/polynomial.o %/%oloop_matrix.f + $(FC) $(patsubst -O%,,$(subst -fbounds-check,,$(FFLAGS))) \ + $(POLYNOMIAL_OPTIMIZATION) $(POLYNOMIAL_BOUNDS_CHECK) \ + -c $< -o $@ $(LOOP_INCLUDE) + +%/polynomial.o : %/polynomial.f + $(FC) $(patsubst -O%,,$(subst -fbounds-check,,$(FFLAGS))) \ + $(POLYNOMIAL_OPTIMIZATION) $(POLYNOMIAL_BOUNDS_CHECK) \ + -c $< -o $@ $(LOOP_INCLUDE) + + +$(DOTO) : $(DOTF) $(POLYNOMIAL) $(OLP_POLYNOMIAL) + $(FC) $(FFLAGS) -c $< -o $@ $(LOOP_INCLUDE) + +$(DOTO) : $(DOTF) + $(FC) $(FFLAGS) -c $< -o $@ $(LOOP_INCLUDE) + +$(OLP): $(OLP_PROCESS) $(LIBS) mg5_citation.o + $(FC) -shared $(OLP_PROCESS) mg5_citation.o -o libMadLoop.$(dylibext) $(LINKLIBS) + +$(OLP)_static: $(OLP_PROCESS) + ar rcs libMadLoop.$(libext) $(OLP_PROCESS) + mv libMadLoop.$(libext) $(MADLOOP_LIB) + +../$(OLP): + rm -f libMadLoop.$(dylibext) + ln -s ../libMadLoop.$(dylibext) + cd $(ROOT)/SubProcesses; make $(OLP) + +../$(OLP)_static: + cd $(ROOT)/SubProcesses; make $(OLP)_static + +libMadLoop.$(dylibext): ../$(OLP) + +WRAPPER_SRCS := $(wildcard */f2py_wrapper.f) +WRAPPER_OBJS := $(patsubst %.f,%.o,$(wildcard */f2py_wrapper.f)) + +%/f2py_wrapper.o: %/f2py_wrapper.f + $(MAKE) -C $* f2py_wrapper.o + + + + +ALL_DOTF := $(wildcard */polynomial.f */loop_matrix.f */improve_ps.f */born_matrix.f */CT_interface.f \ + */loop_num.f \ + */helas_calls*.f */mp_compute_loop_coefs.f */mp_helas_calls*.f */coef_construction_*.f \ + */loop_CT_calls_*.f */mp_coef_construction_*.f */TIR_interface.f */COLLIER_interface.f \ + MadLoopParamReader.f MadLoopCommons.f mg5_citation.f */GOLEM_interface.f */compute_color_flows.f \ + */mp_born_amps_and_wfs.f */jamp?_calls_*.f) + +# Convert .f to .o +ALL_DOTO := $(patsubst %.f,%.o,$(ALL_DOTF)) + +ifeq ($(UNAME), Darwin) + LIBALLME_DYNFLAG = -install_name @rpath/liball$(ROOTNAME)_$(MENUM)me.dylib -undefined dynamic_lookup + WHOLE_ARCH=-Wl,-force_load, + NOWHOLE_ARCH= + STAT_LIB = $(WHOLE_ARCH)$(LIBDIR)libcts.$(libext) $(WHOLE_ARCH)$(LIBDIR)libiregi.$(libext) + LD_F2PY= +else + LIBALLME_DYNFLAG = + WHOLE_ARCH= -Wl,--whole-archive + NOWHOLE_ARCH= -Wl,--no-whole-archive + STAT_LIB = $(WHOLE_ARCH) $(LIBDIR)libcts.$(libext) $(LIBDIR)libiregi.$(libext) $(NOWHOLE_ARCH) + LD_F2PY=-lgfortran -lquadmath +endif + +ifeq ($(origin MENUM),undefined) + MENUM=2 +endif + +liball$(ROOTNAME)_$(MENUM)me.$(dylibext): all_matrix.o libMadLoop.$(dylibext) $(WRAPPER_OBJS) $(LIBS) $(OLP) + $(CXX) $(DYNLIBFLAG) $(LIBALLME_DYNFLAG) $(STDLIB_FLAG) -o liball$(ROOTNAME)_$(MENUM)me.$(dylibext) all_matrix.o */f2py_wrapper.o ../Source/DHELAS/*.o ../Source/MODEL/*.o $(STAT_LIB) $(RPATH_LIBS) $(LINK_LOOP_LIBS) $(ALL_DOTO) $(STDLIB) $(LINK_LOOP_LIBS) + + + +libcollier.$(dylibext): + ln -s $(LIBDIR)/collier_lib/libcollier.$(dylibext) || echo "libcolier already linked" + + + +shared: liball$(ROOTNAME)_$(MENUM)me.$(dylibext) + + + + +matrix$(MENUM)py.so: ../$(OLP)_static f2py_wrapper.f + touch __init__.py + $(F2PY) $(MADLOOP_LIB) -m matrix$(MENUM)py -c f2py_wrapper.f --f77exec=$(FC) -L../../lib/ -ldhelas -lmodel $(LINK_LOOP_LIBS) $(STDLIB) + +allmatrix$(MENUM)py.so: $(OLP)_static all_matrix.f $(LIBS) $(WRAPPER) + touch __init__.py + $(F2PY) $(MADLOOP_LIB) -m allmatrix$(MENUM)py -c all_matrix.f $(wildcard $(LOOP_PREFIX)*/f2py_wrapper.f) --f77exec=$(FC) -L../lib/ -ldhelas -lmodel $(LINK_LOOP_LIBS) $(STDLIB) + + +all_matrix$(MENUM)py.so: liball$(ROOTNAME)_$(MENUM)me.$(dylibext) f2py_wrapper.f makefile + LDFLAGS="-Wl,-rpath,$(HERE) -L$(HERE) $(RPATH_LIBS) $(LINK_LOOP_LIBS) $(LD_F2PY)" $(F2PY) -c f2py_wrapper.f -L$(HERE) -lall$(ROOTNAME)_$(MENUM)me -m all_matrix$(MENUM)py + touch all_matrix$(MENUM)py.so + touch __init__.py + + +clean: + @rm -f *.o *.so *.$(libext) *.$(dylibext) diff --git a/UNITTEST_proc/SubProcesses/makefileP b/UNITTEST_proc/SubProcesses/makefileP new file mode 100644 index 0000000000..ad47e08a27 --- /dev/null +++ b/UNITTEST_proc/SubProcesses/makefileP @@ -0,0 +1,55 @@ +include ../../Source/make_opts +SHELL = /bin/bash +HERE := $(dir $(abspath $(firstword $(MAKEFILE_LIST)))) +ROOT_DIR = $(HERE)/../../ +LIBDIR := $(abspath $(HERE)/../../lib) +PDIR := $(strip $(notdir $(patsubst %/,%,$(strip $(HERE))))) +PROG = check +# Absolute path to the process directory; used as an include path so that the +# Fortran compiler can locate process-local .inc files when matrix.f is built +# from a different cwd (needed for python3.12/3.13 / f2py setups). +# Keep this distinct from PDIR (basename) which is used for dylib naming below. +PDIR_FULL:=$(shell dirname $(realpath --no-symlinks $(firstword matrix.f))) +PROG_SPLITORDERS = check_sa_born_splitOrders +LINKLIBS = -L$(LIBDIR) -ldhelas -lmodel +LIBS = $(LIBDIR)/libdhelas.$(libext) $(LIBDIR)/libmodel.$(libext) +LIBS_SHARED = $(LIBDIR)/libdhelas.$(dylibext) $(LIBDIR)/libmodel.$(dylibext) +PROCESS= matrix.o +CHECK_SA= check_sa.o +CHECK_SA_SPLITORDERS= check_sa_born_splitOrders.o + +F_INCLUDE = -I$(ROOT_DIR)/Source/DHELAS -I$(ROOT_DIR)/Source/MODEL -I$(PDIR_FULL) +FFLAGS += $(F_INCLUDE) + +$(PROG): $(LIBS) $(PROCESS) $(CHECK_SA) makefile + $(FC) $(FFLAGS) -o $(PROG) $(PROCESS) $(CHECK_SA) $(LINKLIBS) + +$(PROG_SPLITORDERS): $(PROCESS) $(CHECK_SA_SPLITORDERS) makefile $(LIBS) + $(FC) $(FFLAGS) -o $(PROG) $(PROCESS) $(CHECK_SA_SPLITORDERS) $(LINKLIBS) + +driver.f: nexternal.inc pmass.inc ngraphs.inc coupl.inc + +$(LIBDIR)/libdhelas.$(libext): + $(MAKE) -C "$(LIBDIR)/../Source/DHELAS" +$(LIBDIR)/libmodel.$(libext): + $(MAKE) -C "$(LIBDIR)/../Source/DHELAS" +$(LIBDIR)/libdhelas.$(dylibext): + $(MAKE) -C "$(LIBDIR)/../Source/DHELAS" shared +$(LIBDIR)/libmodel.$(dylibext): + $(MAKE) -C "$(LIBDIR)/../Source/MODEL" shared + +# For python linking (require f2py part of numpy) +ifeq ($(origin MENUM),undefined) + MENUM=2 +endif + +libme$(PDIR).$(dylibext): $(LIBDIR)/libdhelas.$(dylibext) $(LIBDIR)/libmodel.$(dylibext) matrix.o + gfortran $(DYNLIBFLAG) $(RPATHFLAG)libme$(PDIR).$(dylibext) -o libme$(PDIR).$(dylibext) matrix.o ../../Source/DHELAS/*.o ../../Source/MODEL/*.o + +matrix$(MENUM)py.so: f2py_matrix_wrapper.f libme$(PDIR).$(dylibext) makefile + touch __init__.py + LDFLAGS="-Wl,-rpath,$(HERE)" $(F2PY) -c f2py_matrix_wrapper.f -L$(HERE) -lme$(PDIR) $(LINKLIBS) -m matrix$(MENUM)py + touch matrix$(MENUM)py.so + cp $(LIBDIR)/*$(dylibext) . + + diff --git a/UNITTEST_proc/SubProcesses/mg5_citation.f b/UNITTEST_proc/SubProcesses/mg5_citation.f new file mode 100644 index 0000000000..8bd4953454 --- /dev/null +++ b/UNITTEST_proc/SubProcesses/mg5_citation.f @@ -0,0 +1,91 @@ + subroutine cite(key, context) +c*********************************************************************** +c Record that the reference identified by the INSPIRE texkey `key` +c was used by this run, optionally for the purpose described by the +c free-text `context`. +c +c Each call appends a single line +c keycontext +c to the per-process file +c $MG5_CITATION_DIR/cite...log +c (de-duplicated within the process). The orchestrating Python layer +c collects every such file at the end of the run and turns them into a +c ready-to-use citations.bib together with a human-readable summary. +c +c A per-process file name means there is never a cross-process write +c race, on any filesystem. When MG5_CITATION_DIR is unset the routine +c is a silent no-op, so it is safe to call unconditionally. Any I/O +c failure is swallowed: citation tracking must never abort a run. +c*********************************************************************** + implicit none +c +c Arguments +c + character*(*) key, context +c +c Local parameters +c + integer maxcite + parameter (maxcite=500) + integer reclen + parameter (reclen=320) +c +c Saved per-process state (the keys already written) +c + character*(reclen) seen(maxcite) + integer nseen + save seen, nseen + data nseen /0/ +c +c Local variables +c + character*512 cdir + character*1024 fname + character*(reclen) record + character*256 host + integer dirlen, st, pid, i, lun + logical used +c +c----- +c Begin Code +c----- +c enabled only when MG5_CITATION_DIR points somewhere + call get_environment_variable('MG5_CITATION_DIR', + & cdir, dirlen, st) + if (dirlen .le. 0) return + if (dirlen .gt. len(cdir)) return +c +c the de-duplication record is keycontext + record = trim(key)//char(9)//trim(context) +c +c guard the shared state/file against OpenMP threads of this process +c$omp critical (mg5_cite) + used = .false. + do i = 1, nseen + if (seen(i) .eq. record) used = .true. + enddo +c + if (.not. used) then + if (nseen .lt. maxcite) then + nseen = nseen + 1 + seen(nseen) = record + endif +c build /cite...log + host = 'localhost' + call hostnm(host, st) + pid = getpid() + write(fname, '(a,a,a,a,i0,a)') cdir(1:dirlen), + & '/cite.', trim(host), '.', pid, '.log' +c append the record, swallowing any failure + lun = 87 + open(unit=lun, file=fname, status='unknown', + & position='append', iostat=st) + if (st .eq. 0) then + write(lun, '(a)', iostat=st) trim(record) + close(lun) + endif + endif +c$omp end critical (mg5_cite) +c + return + end diff --git a/UNITTEST_proc/SubProcesses/mp_coupl.inc b/UNITTEST_proc/SubProcesses/mp_coupl.inc new file mode 120000 index 0000000000..8b7845362c --- /dev/null +++ b/UNITTEST_proc/SubProcesses/mp_coupl.inc @@ -0,0 +1 @@ +../Source/MODEL/mp_coupl.inc \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/mp_coupl_same_name.inc b/UNITTEST_proc/SubProcesses/mp_coupl_same_name.inc new file mode 120000 index 0000000000..8bb4c2a03f --- /dev/null +++ b/UNITTEST_proc/SubProcesses/mp_coupl_same_name.inc @@ -0,0 +1 @@ +../Source/MODEL/mp_coupl_same_name.inc \ No newline at end of file diff --git a/UNITTEST_proc/TemplateVersion.txt b/UNITTEST_proc/TemplateVersion.txt new file mode 100644 index 0000000000..437459cd94 --- /dev/null +++ b/UNITTEST_proc/TemplateVersion.txt @@ -0,0 +1 @@ +2.5.0 diff --git a/madgraph/core/helas_objects.py b/madgraph/core/helas_objects.py index fc7562fb61..fd70d6a8b5 100755 --- a/madgraph/core/helas_objects.py +++ b/madgraph/core/helas_objects.py @@ -4000,6 +4000,8 @@ def default_setup(self): # Cache for get_quartic_amplitude_merges(), needed both by the helas # calls and by the colour amplitudes. Runtime only, like the above. self.quartic_amplitude_merges = None + # Cache for get_quartic_current_sums(), same reason + self.quartic_current_sums = None def filter(self, name, value): """Filter for valid diagram property values.""" @@ -4420,6 +4422,16 @@ def reuse_outdated_wavefunctions(self, helas_diagrams): wf.set('me_id',wf.get('number')) return helas_diagrams + # A current sum is written out as soon as the later of the two + # currents it reads is made, so both have to still be there then -- + # which this analysis has no way of knowing on its own. + sums = self.get_quartic_current_sums()[0] + read_after = {} + for cubic, quartic in [(entry[0], entry[1]) for entry in sums]: + read_after.setdefault(max(cubic.get('number'), + quartic.get('number')), []).append( + (cubic.get('number'), quartic.get('number'))) + # First compute the first/last appearance of each wavefunctions # first takes the line number and return the id of the created wf # last_lign takes the id of the wf and return the line number @@ -4433,6 +4445,9 @@ def reuse_outdated_wavefunctions(self, helas_diagrams): last_lign[wfin.get('number')] = pos assert wfin.get('number') in list(first.values()) first[pos] = wf.get('number') + for cubic, quartic in read_after.get(wf.get('number'), []): + last_lign[cubic] = pos + last_lign[quartic] = pos for amp in diag['amplitudes']: pos+=1 for wfin in amp.get('mothers'): @@ -5317,12 +5332,15 @@ def get_num_configs(self): def get_number_of_wavefunctions(self): """Gives the total number of wavefunctions for this ME""" - out = max([wf.get('me_id') for wfs in self.get('diagrams') + # the current sums get a slot each, at the end and never reused + extra = self.get_number_of_quartic_current_sums() + + out = max([wf.get('me_id') for wfs in self.get('diagrams') for wf in wfs.get('wavefunctions')]) - if out: - return out + if out: + return out + extra return sum([ len(d.get('wavefunctions')) for d in \ - self.get('diagrams')]) + self.get('diagrams')]) + extra def get_all_wavefunctions(self): """Gives a list of all wavefunctions for this ME""" @@ -6183,6 +6201,187 @@ def compute_quartic_amplitude_merges(self): return dict((source, value) for source, value in res.items() if source not in targets) + def get_quartic_current_sums(self): + """Return the current sums which take a quartic amplitude away. + + Where a quartic current and the cubic current carrying the same colour + factor feed the same vertex, the two amplitudes they give differ by + that one line and by nothing else. Summing the two currents once and + calling the amplitude on the sum therefore gets both contributions out + of a single call: + + TMP = W1 + c*W4 + CALL VVV1_0(..., TMP, AMP(t)) + + instead of one call for AMP(t) and one for the quartic AMP(s) which is + then added to it. The sum is one addition and is shared by every + amplitude which uses it, so it replaces as many calls as it has users. + + Only the amplitudes are treated. A sum sitting deeper would have to be + carried through every current above it, and those currents are shared + with diagrams which must not get the extra term -- see + docs/gluon-quartic-plan.md. + + Returns (sums, uses, folded): + sums [(cubic wavefunction, quartic wavefunction, coefficient)] + uses {amplitude number: {cubic wavefunction number: sums index}} + folded set of amplitude numbers the sums make unnecessary + """ + + if self.quartic_current_sums is None: + self.quartic_current_sums = self.compute_quartic_current_sums() + return self.quartic_current_sums + + def get_number_of_quartic_current_sums(self): + """How many extra wavefunction slots the current sums need.""" + + return len(self.get_quartic_current_sums()[0]) + + def compute_quartic_current_sums(self): + """Work out the current sums, see get_quartic_current_sums.""" + + merges = self.get_quartic_amplitude_merges() + if not merges: + return [], {}, set() + + model = self.get('processes')[0].get('model') + unrollable = diagram_generation.get_unrollable_quartic_vertices(model) + cubic_ids = diagram_generation.get_unrollable_cubic_ids(model) + + amplitudes = {} + available = {} + written = set() + for diagram in self.get('diagrams'): + for wavefunction in diagram.get('wavefunctions'): + written.add(wavefunction.get('number')) + for amplitude in diagram.get('amplitudes'): + amplitudes[amplitude.get('number')] = amplitude + # the currents which exist by the time it is written out + available[amplitude.get('number')] = frozenset(written) + + # For each target, the substitutions each of its merges asks for + candidates = {} + for source, (target, coeff) in merges.items(): + pairs = self.match_quartic_mothers(amplitudes[source], + amplitudes[target], + unrollable, cubic_ids) + if not pairs: + continue + # the quartic current has to be there when the target is written + if any(quartic.get('number') not in available[target] + for cubic, quartic in pairs): + continue + key = frozenset((cubic.get('number'), quartic.get('number')) + for cubic, quartic in pairs) + candidates.setdefault(target, {})[key] = (source, coeff, pairs) + + sums, uses, folded = [], {}, set() + index = {} + for target in sorted(candidates): + entries = candidates[target] + singles = dict((next(iter(key)), value) + for key, value in entries.items() if len(key) == 1) + + # Substituting several mothers at once also produces the amplitude + # with all of them substituted, so every subset has to be a merge + # into this same target, with the product of the coefficients. + # Keep the substitutions which pass, drop the ones which do not. + chosen = [] + for pair in sorted(singles): + trial = chosen + [pair] + if all(self.subset_is_merged(entries, singles, combination) + for size in range(2, len(trial) + 1) + for combination in itertools.combinations(trial, size)): + chosen = trial + if not chosen: + continue + + for size in range(1, len(chosen) + 1): + for combination in itertools.combinations(chosen, size): + folded.add(entries[frozenset(combination)][0]) + for pair in chosen: + source, coeff, pairs = singles[pair] + cubic, quartic = pairs[0] + if (pair, coeff) not in index: + index[(pair, coeff)] = len(sums) + sums.append((cubic, quartic, coeff)) + uses.setdefault(target, {})[cubic.get('number')] = \ + index[(pair, coeff)] + + return sums, uses, folded + + @staticmethod + def subset_is_merged(entries, singles, combination): + """Is the amplitude with all of combination substituted a merge into + the same target, weighing the product of the single coefficients?""" + + entry = entries.get(frozenset(combination)) + if entry is None: + return False + weight = 1 + for pair in combination: + weight *= singles[pair][1] + return entry[1] == weight + + @staticmethod + def match_quartic_mothers(source, target, unrollable, cubic_ids): + """Pair the mothers up where the source amplitude carries the quartic + current and the target the cubic one taking the same four lines. + + Returns [] unless the two are otherwise one and the same vertex, which + is what makes the substitution a plain swap of one argument.""" + + if source.get('interaction_id') != target.get('interaction_id') or \ + source.get('color_key') != target.get('color_key'): + return [] + + source_mothers = dict((mother.get('number'), mother) + for mother in source.get('mothers')) + target_mothers = dict((mother.get('number'), mother) + for mother in target.get('mothers')) + only_source = [source_mothers[number] for number in source_mothers + if number not in target_mothers] + only_target = [target_mothers[number] for number in target_mothers + if number not in source_mothers] + if not only_source or len(only_source) != len(only_target): + return [] + + res = [] + for quartic in only_source: + hit = [cubic for cubic in only_target + if HelasMatrixElement.is_unrolled_pair(quartic, cubic, + unrollable, + cubic_ids)] + if len(hit) != 1: + return [] + res.append((hit[0], quartic)) + if len(set(cubic.get('number') for cubic, quartic in res)) != len(res): + return [] + return res + + @staticmethod + def is_unrolled_pair(quartic, cubic, unrollable, cubic_ids): + """True when the cubic current is the pair of vertices the quartic one + factorises into: same four lines coming in, same line going out.""" + + if quartic.get('interaction_id') not in unrollable or \ + cubic.get('interaction_id') not in cubic_ids or \ + quartic.get('number_external') != cubic.get('number_external'): + return False + + wanted = sorted(mother.get('number') + for mother in quartic.get('mothers')) + for inner in cubic.get('mothers'): + if inner.get('interaction_id') not in cubic_ids or \ + len(inner.get('mothers')) != 2: + continue + if sorted([mother.get('number') + for mother in inner.get('mothers')] + + [other.get('number') for other in cubic.get('mothers') + if other is not inner]) == wanted: + return True + return False + def sort_split_orders(self, split_orders): """ Sort the 'split_orders' list given in argument so that the orders of smaller weights appear first. Do nothing if not all split orders have diff --git a/madgraph/iolibs/helas_call_writers.py b/madgraph/iolibs/helas_call_writers.py index fecc12effd..6873bcd26f 100755 --- a/madgraph/iolibs/helas_call_writers.py +++ b/madgraph/iolibs/helas_call_writers.py @@ -231,21 +231,74 @@ def get_matrix_element_calls(self, matrix_element): me = matrix_element.get('diagrams') matrix_element.reuse_outdated_wavefunctions(me) + # A current sum has to be written out once both currents are there. + # Doing it as soon as the later of the two is made keeps them alive: + # a slot is only handed on after its last use, and the cubic one is + # still needed by the amplitude the sum is for. + sums, uses, folded = self.get_quartic_current_sums(matrix_element) + first_sum = matrix_element.get_number_of_wavefunctions() - len(sums) + after = {} + for i, (cubic, quartic, coeff) in enumerate(sums): + after.setdefault(max(cubic.get('number'), quartic.get('number')), + []).append(i) + res = [] for diagram in matrix_element.get('diagrams'): - - - res.extend([ self.get_wavefunction_call(wf) for \ - wf in diagram.get('wavefunctions') ]) + + + for wf in diagram.get('wavefunctions'): + res.append(self.get_wavefunction_call(wf)) + for i in after.get(wf.get('number'), []): + cubic, quartic, coeff = sums[i] + res.extend(self.get_current_sum_lines( + first_sum + 1 + i, cubic, quartic, coeff)) res.append("# Amplitude(s) for diagram number %d" % \ diagram.get('number')) for amplitude in diagram.get('amplitudes'): - res.append(self.get_amplitude_call(amplitude)) + if amplitude.get('number') in folded: + # summed into another amplitude through a current sum + continue + res.append(self.get_amplitude_call_on_sums( + amplitude, uses.get(amplitude.get('number')), first_sum)) res.extend(self.get_amplitude_merge_lines(matrix_element)) return res + def get_quartic_current_sums(self, matrix_element): + """The current sums to write out. Only the Fortran writer knows how to + emit one, see FortranUFOHelasCallWriter.""" + + return [], {}, set() + + def get_current_sum_lines(self, number, cubic, quartic, coeff): + """Lines building one current sum. Fortran only.""" + + raise NotImplementedError + + def get_amplitude_call_on_sums(self, amplitude, substitution, first_sum): + """The amplitude call, reading the current sums in place of the cubic + currents they were built from. + + The slot is swapped on the mother itself and put back straight away, + the same way get_loop_amplitude_helas_calls relabels its externals.""" + + if not substitution: + return self.get_amplitude_call(amplitude) + + original = [] + for mother in amplitude.get('mothers'): + index = substitution.get(mother.get('number')) + if index is None: + continue + original.append((mother, mother.get('me_id'))) + mother.set('me_id', first_sum + 1 + index) + try: + return self.get_amplitude_call(amplitude) + finally: + for mother, me_id in original: + mother.set('me_id', me_id) + def get_amplitude_merge_lines(self, matrix_element): """Lines summing the quartic contributions into the amplitude which carries the same colour factor. Only the Fortran writer implements @@ -1049,9 +1102,13 @@ def get_amplitude_merge_lines(self, matrix_element): merges = matrix_element.get_quartic_amplitude_merges() if not merges: return [] + # these were never computed: their current was summed instead + folded = self.get_quartic_current_sums(matrix_element)[2] res = ['# Sum the quartic contributions into their cubic partner'] for source in sorted(merges): + if source in folded: + continue target, coeff = merges[source] if coeff == 1: res.append('AMP(%d) = AMP(%d) + AMP(%d)' % @@ -1064,6 +1121,32 @@ def get_amplitude_merge_lines(self, matrix_element): (target, target, float(coeff), source)) return res + def get_quartic_current_sums(self, matrix_element): + """The current sums, see HelasMatrixElement.get_quartic_current_sums""" + + return matrix_element.get_quartic_current_sums() + + def get_current_sum_lines(self, number, cubic, quartic, coeff): + """Sum the quartic current into the cubic one carrying the same colour + factor, so that the amplitude reading the sum gets both at once. + + The two share their momentum, so only the wavefunction itself is + added; everything else is taken over from the cubic current.""" + + out = self.format_helas_object('W(', '%d') % number + from_cubic = self.format_helas_object('W(', '%d') % cubic.get('me_id') + from_quartic = self.format_helas_object('W(', '%d') % \ + quartic.get('me_id') + + if coeff == 1: + added = '%s%%W(:)' % from_quartic + elif coeff == -1: + added = '-%s%%W(:)' % from_quartic + else: + added = '(%.15e)*%s%%W(:)' % (float(coeff), from_quartic) + return ['%s = %s' % (out, from_cubic), + '%s%%W(:) = %s%%W(:) + %s' % (out, from_cubic, added)] + def __init__(self, argument={}, hel_sum = False, options={}): """Allow generating a HelasCallWriter from a Model.The hel_sum argument specifies if amplitude and wavefunctions must be stored specifying the diff --git a/tests/unit_tests/core/test_diagram_generation.py b/tests/unit_tests/core/test_diagram_generation.py index 6ccc89d187..d1fc1d98c7 100755 --- a/tests/unit_tests/core/test_diagram_generation.py +++ b/tests/unit_tests/core/test_diagram_generation.py @@ -4214,6 +4214,90 @@ def test_expand_gg_ttxgg(self): self.check_expansion([21, 21], [6, -6, 21, 21], 123, 54) + def test_current_sums_gg_ggg(self): + """g g > g g g: seven quartic amplitudes become a current sum""" + + self.check_current_sums([21, 21], [21, 21, 21], 7, 7) + + def test_current_sums_gg_gggg(self): + """g g > g g g g: thirty sums take sixty amplitude calls away""" + + self.check_current_sums([21, 21], [21, 21, 21, 21], 30, 60) + + def test_current_sums_inactive_by_default(self): + """No current sum unless madgraph.merge_quartic_vertices is set""" + + import madgraph.core.helas_objects as helas_objects + + madgraph.merge_quartic_vertices = False + myleglist = base_objects.LegList( + [base_objects.Leg({'id':21, 'state':False})] * 2 + + [base_objects.Leg({'id':21, 'state':True})] * 3) + matrix_element = helas_objects.HelasMatrixElement( + diagram_generation.Amplitude(base_objects.Process( + {'legs':myleglist, 'model':self.base_model}))) + self.assertEqual(matrix_element.get_quartic_current_sums(), + ([], {}, set())) + self.assertEqual( + matrix_element.get_number_of_quartic_current_sums(), 0) + + def check_current_sums(self, initial, final, nsum, nfolded): + """A current sum has to stand for exactly the amplitude it takes away: + the same vertex, with the quartic current where the target has the + cubic one.""" + + import madgraph.core.helas_objects as helas_objects + + madgraph.merge_quartic_vertices = True + myleglist = base_objects.LegList( + [base_objects.Leg({'id':pdg, 'state':False}) for pdg in initial] + + [base_objects.Leg({'id':pdg, 'state':True}) for pdg in final]) + matrix_element = helas_objects.HelasMatrixElement( + diagram_generation.Amplitude(base_objects.Process( + {'legs':myleglist, 'model':self.base_model}))) + + sums, uses, folded = matrix_element.get_quartic_current_sums() + merges = matrix_element.get_quartic_amplitude_merges() + self.assertEqual(len(sums), nsum) + self.assertEqual(len(folded), nfolded) + self.assertEqual(matrix_element.get_number_of_quartic_current_sums(), + nsum) + + amplitudes = dict((amplitude.get('number'), amplitude) + for diagram in matrix_element.get('diagrams') + for amplitude in diagram.get('amplitudes')) + unrollable = diagram_generation.get_unrollable_quartic_vertices( + self.base_model) + + # every sum is a quartic current against the cubic pair it splits into + for cubic, quartic, coeff in sums: + self.assertTrue(helas_objects.HelasMatrixElement.is_unrolled_pair( + quartic, cubic, unrollable, self.cubic_ids)) + + # and every amplitude taken away is the target with some of the + # substitutions applied, which is exactly what reading the sums gives + for source in folded: + self.assertIn(source, merges) + target, coeff = merges[source] + self.assertIn(target, uses) + swap = dict((cubic, sums[index][1].get('number')) + for cubic, index in uses[target].items()) + mothers = [mother.get('number') + for mother in amplitudes[target].get('mothers')] + options = [] + for size in range(1, len(swap) + 1): + for combination in itertools.combinations(sorted(swap), size): + options.append(sorted(swap[number] + if number in combination else number + for number in mothers)) + self.assertIn(sorted(mother.get('number') for mother in + amplitudes[source].get('mothers')), options) + self.assertEqual(amplitudes[source].get('interaction_id'), + amplitudes[target].get('interaction_id')) + + # a folded amplitude must not also be a target + self.assertFalse(folded & set(uses)) + def test_seed_inactive_by_default(self): """Nothing changes unless madgraph.merge_quartic_vertices is set""" From d8f21b6f5508a3e35d6c8ae14ae3ce942d30103a Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 07:04:15 +0200 Subject: [PATCH 11/39] record that the current sum lands at the amplitudes Step 4 is done where the vertex reading the sum is an amplitude, which is where it is safe: nothing sits above one, so no consumer can be handed a term it must not have. Deeper it stays blocked for the counting reason already written down. Adds the slot-reuse trap as a pitfall -- a wavefunction number is not a slot, and anything emitting an extra read has to extend the lifetime there -- and corrects pitfall 7, which turns out to be wrong at seven gluons: the JAMP block alone is worth +3.1% there. Co-Authored-By: Claude Opus 5 --- docs/gluon-quartic-plan.md | 109 ++++++++++++++++++++++++++++--------- 1 file changed, 84 insertions(+), 25 deletions(-) diff --git a/docs/gluon-quartic-plan.md b/docs/gluon-quartic-plan.md index 61b6dc8c81..ad46e20461 100644 --- a/docs/gluon-quartic-plan.md +++ b/docs/gluon-quartic-plan.md @@ -67,7 +67,8 @@ property the whole optimisation needs. | `1c1722ae8` | revert of the auxiliary-particle generation | | `98d288f41` | `reroot_diagram`, validated 755/755 — probably NOT needed under the seed rule | | `25fc6d1cc` | step 1, the seed rule inside `reduce_leglist` | -| `1b9474f69` | step 2+3, `expand_seed_diagrams` and the recorded links | +| `7da06bac7` | step 2+3, `expand_seed_diagrams` and the recorded links | +| `8e634cf9a` | step 4, `TMP = W1 + c*W4` at the amplitudes | Useful pieces to keep: `get_unrollable_quartic_vertices`, `unroll_quartic_vertices`, `diagram_colour_signature`, `UnrollDiagramTag`, @@ -105,7 +106,36 @@ with the colour algebra. target for target with `unroll_quartic_vertices`, which stays as the independent colour-algebra cross-check. -**Step 4 — the current sum.** BLOCKED, and the reason is structural. Measured +**Step 4 — the current sum.** DONE at the amplitudes, `8e634cf9a`, and +blocked deeper. `TMP = W1 + c*W4` where a quartic current and its cubic +partner feed the same vertex; the amplitude reads the sum and the quartic +amplitude is never computed: + +``` +W(20) = W(19) +W(20)%W(:) = W(19)%W(:) + W(12)%W(:) +CALL VVV1_0(W(4),W(5),W(20),GC_10,AMP(33)) +``` + +The sum is shared by every amplitude reading it, so it pays for as many calls +as it has users: 60 amplitude calls for 30 sums at six gluons, 432 for 60 at +seven. Substituting several mothers of one amplitude also produces the +amplitude with all of them substituted, so every subset has to be a merge into +that same target weighing the product of the coefficients — that check is what +keeps the count honest. + +Two things it costs. `reuse_outdated_wavefunctions` works out when a slot is +free from the diagrams alone and cannot see the extra read, so it has to be +told, or the two currents get handed the same slot (`W(11) + W(11)`). And the +sums take a slot each, never reused: `NWAVEFUNCS` 51 -> 91 at six gluons. + +| | `g g > g g g` | `g g > g g g g` | `g g > 5 g` | +|---|---|---|---| +| helas calls | 94 -> 93 + 7 sums | 637 -> 612 + 30 | 8159 -> 7784 + 60 | +| JAMP lines | 131 -> 101 | 1082 -> 688 | 23672 -> 7864 | +| per call | 34.88 -> 35.12 s | 47.77 -> 46.02 s | 42.16 -> 39.80 s | + +**The sum stays at the amplitudes.** Measured on the reconstructed matrix element (`g g > g g g g`): of the 275 places where a cubic current is fed by another cubic current *and* the quartic partner taking the same four lines exists, 225 are the last vertex — the amplitude @@ -137,10 +167,20 @@ fact 2 requires. Not fixable by choosing the spelling more cleverly: the counting alone rules it out, and `g g > g g` — the one row with no collision — is also the one process where the seed rule reaches every partner. -What would work is a partial rewrite — build `TMP = W1 + W4` as a *third* -current, hand it only to the consumers which do correspond, and leave W1 and -W4 serving the rest. That splits shared consumers and cascades upward; it is -a DAG rewriting problem, not this plan. +That is why the sum is taken only where the vertex reading it is an +*amplitude*: there is nothing above it, so no consumer can be handed a term +it must not have and the substitution is a plain swap of one argument. A sum +at a current would have to be carried through every current above it, and +those are shared. What would work there is a partial rewrite — hand the sum +only to the consumers which do correspond and leave W1 and W4 serving the +rest — which splits shared consumers and cascades upward. That is a DAG +rewriting problem, not this plan. + +The same counting is what leaves the two-substitution cases at seven gluons +on the table: their target has a source with both mothers substituted, but +the source with only the *other* one substituted is spelled with a different +rooting, so the subset check refuses it. 432 of the 864 amplitude calls the +structure allows. **Step 5 — validate and time.** DONE. `|M|^2` for `g g > N g`, N=2..5, and per-call timing from the shipped `check` driver, which already loops @@ -148,42 +188,53 @@ per-call timing from the shipped `check` driver, which already loops | | `g g > g g g g` | `g g > 5 g` | |---|---|---| -| flag off | 47.73 / 47.77 s | 42.15 s | -| flag on, before steps 1-3 | 47.76 s | 40.86 s | -| flag on, at HEAD | 48.03 / 48.07 s | 40.41 s | +| flag off | 47.73 / 47.77 / 47.80 s | 42.15 / 42.16 s | +| flag on, before steps 1-4 | 47.76 s | 40.86 s | +| flag on, steps 1-3 only | 48.03 / 48.07 s | 40.41 s | +| flag on, at HEAD | 46.14 / 45.90 s | 39.80 s | and the code that produces it: | | helas calls | JAMP lines | |---|---|---| | flag off | 637 / 8159 | 1082 / 23672 | -| flag on, before steps 1-3 | 637 / 8159 | 688 / 8012 | -| flag on, at HEAD | 672 / 8216 | 688 / 7864 | +| flag on, before steps 1-4 | 637 / 8159 | 688 / 8012 | +| flag on, steps 1-3 only | 672 / 8216 | 688 / 7864 | +| flag on, at HEAD | 612 + 30 / 7784 + 60 | 688 / 7864 | + +So the flag is worth **+3.8% at six gluons and +5.6% at seven**. The JAMP +shrink from `fcd8218b6` carries seven gluons on its own; six gluons only +turns positive with the current sum, because the reconstruction deviates from +the canonical decomposition — which is the whole point — and thereby weakens +the wavefunction CSE, 35 calls at six gluons and 57 at seven. Five gluons is +a wash (34.88 -> 35.12 s): 7 sums against 7 calls is too little to pay for +the 14 extra slots. -So the flag is worth **+4.1% at seven gluons and -0.6% at six**, and nearly -all of that is the amplitude sum from `fcd8218b6` shrinking the JAMP block. -Steps 1-3 cost 35 helas calls at six gluons for nothing, and pay for -themselves only at seven (57 more calls, 148 fewer JAMP lines, net +1.1%). -The reconstruction deviates from the canonical decomposition, which is the -whole point, but it also weakens the wavefunction CSE — and without step 4 -there is nothing on the other side of that trade. +`|M|^2` bit-identical at four and five gluons, 1e-15 at six and seven, and +unchanged for `g g > t t~ g g` and `u u~ > g g g`. With the flag off, `matrix.f` is byte-identical to `3b3ed9e85` for N=2..5. ## Where to go next -The current sum needs a node to have exactly one rooting *per merge*, which a -diagram list cannot give. Two ways out, both bigger than this plan: +What is left is the sums which do not sit at an amplitude, and they need a +node to have exactly one rooting *per merge*, which a diagram list cannot +give. Three ways on, in increasing size: -1. **Drop the diagram list for the currents.** Build the wavefunctions by a - Berends-Giele recursion over subsets — at each node, cubic pair plus - quartic, which generates exactly the matchings and never double counts — - and keep the 220 diagrams only for what they are actually needed for - (multichannel, `matrix.ps`). +1. **The second substitution.** Cheapest of the three and worth another 432 + amplitude calls at seven gluons. The subset check refuses a + two-substitution target because the single it needs is spelled with a + different rooting; finding that amplitude by its diagram and colour chain + rather than by its mothers would take it. 2. **Partial CSE.** Keep the DAG, add `TMP = W1 + W4` alongside W1 and W4, and split the consumers. Bounded gain: at six gluons only 2 of the 6 quartic consumers correspond, so it saves 2 subtrees per node out of 50 nodes. +3. **Drop the diagram list for the currents.** Build the wavefunctions by a + Berends-Giele recursion over subsets — at each node, cubic pair plus + quartic, which generates exactly the matchings and never double counts — + and keep the 220 diagrams only for what they are actually needed for + (multichannel, `matrix.ps`). Anything that fragments the diagram list to get a per-rooting copy runs into pitfall 1, and anything that expands each seed independently double counts — @@ -222,6 +273,14 @@ graph (225 instead of 105 at six gluons). those pairs (`TMP_JAMP(2) = AMP(1) + AMP(4)`). They do shrink the JAMP block (1091 -> 697 lines at six gluons), which helps the optimiser and compile time. Expect the speedup to come from the currents, not from these. + *Measured since:* wrong at seven gluons, where the JAMP block goes 23672 -> + 7864 lines and that alone is +3.1%. Right at six, where it is a wash. +8. **A wavefunction number is not a slot.** `reuse_outdated_wavefunctions` + hands the same `me_id` to wavefunctions whose lifetimes do not overlap, and + works those lifetimes out from the diagrams alone. Anything emitting an + extra read of a wavefunction has to extend the lifetime there, or it reads + whatever else has since been written into that slot -- which showed up as + `W(11)%W(:) = W(11)%W(:) + W(11)%W(:)`. ## Measuring From bfbf910efd2a39d5f7cec397df9369daada2ffa1 Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 07:22:48 +0200 Subject: [PATCH 12/39] measure what the second substitution would really be worth The plan claimed another 432 amplitude calls at seven gluons were waiting to be picked up. They are not. Substituting two mothers of one amplitude also produces the amplitude with both substituted, weighing the product of the two coefficients, and the merge map has to agree -- but the sign from diagram_colour_signature does not factorise over two contractions. Taking the double's coefficient over the known single's, no merge source into the target weighs what the missing single would have to weigh for 150 of the 432. So the ceiling is at most 282, on top of the identification problem: all 432 have exactly one of the two singles present, the other being the same diagram rooted differently. subset_is_merged already refuses these, which is what keeps the current code sound. Co-Authored-By: Claude Opus 5 --- docs/gluon-quartic-plan.md | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/docs/gluon-quartic-plan.md b/docs/gluon-quartic-plan.md index ad46e20461..7b00f4079f 100644 --- a/docs/gluon-quartic-plan.md +++ b/docs/gluon-quartic-plan.md @@ -180,7 +180,8 @@ The same counting is what leaves the two-substitution cases at seven gluons on the table: their target has a source with both mothers substituted, but the source with only the *other* one substituted is spelled with a different rooting, so the subset check refuses it. 432 of the 864 amplitude calls the -structure allows. +structure allows — and the rest are not simply waiting to be picked up, see +"where to go next". **Step 5 — validate and time.** DONE. `|M|^2` for `g g > N g`, N=2..5, and per-call timing from the shipped `check` driver, which already loops @@ -221,11 +222,26 @@ What is left is the sums which do not sit at an amplitude, and they need a node to have exactly one rooting *per merge*, which a diagram list cannot give. Three ways on, in increasing size: -1. **The second substitution.** Cheapest of the three and worth another 432 - amplitude calls at seven gluons. The subset check refuses a - two-substitution target because the single it needs is spelled with a - different rooting; finding that amplitude by its diagram and colour chain - rather than by its mothers would take it. +1. **The second substitution.** Cheapest of the three, ceiling 432 amplitude + calls at seven gluons, but measured to be at most 282 of them and possibly + much less. Two things stand in the way and only the first is bookkeeping: + + *Identification.* All 432 targets which have a two-substitution source have + exactly one of the two singles present; the other is the same diagram + rooted differently, so it is a different amplitude object with different + mothers and `match_quartic_mothers` cannot see it. Finding it by its + diagram and colour chain — the frame `compute_quartic_amplitude_merges` + already works in — rather than by its mothers would take it. + + *The coefficients have to multiply.* Substituting two mothers also produces + the amplitude with both substituted, weighing the product of the two + coefficients, so the merge map has to agree. It does not always: taking the + double's coefficient over the known single's, the missing single would have + to weigh -1 for 360 of the 432 targets and +1 for 72, and for **150 of them + no merge source into that target weighs that at all**. The sign from + `diagram_colour_signature` does not factorise over two contractions in + general. `subset_is_merged` already refuses those, which is what keeps the + present code sound; extending the identification does not remove the check. 2. **Partial CSE.** Keep the DAG, add `TMP = W1 + W4` alongside W1 and W4, and split the consumers. Bounded gain: at six gluons only 2 of the 6 quartic consumers correspond, so it saves 2 subtrees per node out of 50 From 29b0c670e5b4ba03c3f4139ae9870de47ab3d279 Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 07:49:08 +0200 Subject: [PATCH 13/39] carry the current sum into madevent Two things had to change for the optimisation to survive the madevent path. The sum is now written as CALL SUMW_1(W(a),W(b),W(c)) rather than as two assignments. Helicity recycling rebuilds the whole DAG from the calls alone, so a bare assignment was invisible to it: the summed current never entered the graph and the amplitude reading it died on a KeyError. Written as a call it is an ordinary internal wavefunction taking two mothers and every existing mechanism handles it. sumw_1 and subw_1 go into aloha_functions.f; the coefficient is restricted to +-1, which is all it has ever been. hel_recycle.add_indices could not index an AMP( opening a statement -- the pattern ate the character in front of it, and there is none at the start of the line -- so the fold came out as "AMP(31) = AMP( K,31) + AMP( K,1)" and would not compile. Looking at that character rather than eating it fixes it. Latent until now, since nothing emitted a line starting on AMP(. AMP2 needs no change and is left as it is: the fold lines run before it, so the channel weight is the amplitude including the four gluon contribution, which is what it should be. The quartic diagrams never had an AMP2 entry of their own -- get_amp2_lines skips anything with a four point vertex -- so the folded amplitudes are not referenced anywhere. g g > g g g through madevent, 10000 events, three seeds each: cross section rel. error ME cpu flag off 3.680-3.694e+07 pb 0.326% 52.7 s flag on 3.684-3.694e+07 pb 0.300% 49.0 s so 8% less error for 7% less cpu. Including the four gluon piece in AMP2 makes it a better channel weight, not a worse one. Co-Authored-By: Claude Opus 5 --- aloha/template_files/aloha_functions.f | 40 +++++++++++++++++++++ aloha/template_files/aloha_functions_fd.f | 40 +++++++++++++++++++++ aloha/template_files/aloha_functions_loop.f | 40 +++++++++++++++++++++ madgraph/core/helas_objects.py | 3 ++ madgraph/iolibs/helas_call_writers.py | 28 +++++++-------- madgraph/madevent/hel_recycle.py | 8 +++-- 6 files changed, 141 insertions(+), 18 deletions(-) diff --git a/aloha/template_files/aloha_functions.f b/aloha/template_files/aloha_functions.f index 01aa9d8ad3..09dbd86a33 100644 --- a/aloha/template_files/aloha_functions.f +++ b/aloha/template_files/aloha_functions.f @@ -1923,3 +1923,43 @@ subroutine CombineAmpS(nb, ihels, iwfcts, W1, Wall, Amp) enddo return end + + subroutine sumw_1(w1, w2, wout) +c +c Sum two currents standing for the same off shell line: the four +c gluon current and the pair of three gluon vertices it factorises +c into carry the same colour factor, so the amplitude reading the sum +c gets both contributions from a single call. See +c HelasMatrixElement.get_quartic_current_sums. +c +c The two share their momentum, so only the wavefunction is added and +c everything else is taken over from the first one. +c + use ALOHA_OBJECT + implicit none + type(aloha) w1 + type(aloha) w2 + type(aloha) wout + + wout = w1 + wout%W(:) = w1%W(:) + w2%W(:) + + return + end + + + subroutine subw_1(w1, w2, wout) +c +c As sumw_1, for the contributions which enter with a minus sign. +c + use ALOHA_OBJECT + implicit none + type(aloha) w1 + type(aloha) w2 + type(aloha) wout + + wout = w1 + wout%W(:) = w1%W(:) - w2%W(:) + + return + end diff --git a/aloha/template_files/aloha_functions_fd.f b/aloha/template_files/aloha_functions_fd.f index 2696c80d84..fcac1ac465 100644 --- a/aloha/template_files/aloha_functions_fd.f +++ b/aloha/template_files/aloha_functions_fd.f @@ -2240,3 +2240,43 @@ subroutine define_gauge_dir(q, n) end + + subroutine sumw_1(w1, w2, wout) +c +c Sum two currents standing for the same off shell line: the four +c gluon current and the pair of three gluon vertices it factorises +c into carry the same colour factor, so the amplitude reading the sum +c gets both contributions from a single call. See +c HelasMatrixElement.get_quartic_current_sums. +c +c The two share their momentum, so only the wavefunction is added and +c everything else is taken over from the first one. +c + use ALOHA_OBJECT + implicit none + type(aloha) w1 + type(aloha) w2 + type(aloha) wout + + wout = w1 + wout%W(:) = w1%W(:) + w2%W(:) + + return + end + + + subroutine subw_1(w1, w2, wout) +c +c As sumw_1, for the contributions which enter with a minus sign. +c + use ALOHA_OBJECT + implicit none + type(aloha) w1 + type(aloha) w2 + type(aloha) wout + + wout = w1 + wout%W(:) = w1%W(:) - w2%W(:) + + return + end diff --git a/aloha/template_files/aloha_functions_loop.f b/aloha/template_files/aloha_functions_loop.f index 46561ce7d9..8d558bbe0b 100644 --- a/aloha/template_files/aloha_functions_loop.f +++ b/aloha/template_files/aloha_functions_loop.f @@ -3042,3 +3042,43 @@ subroutine olxxxx(p,ffmass,nhel,nsf,fo) c return end + + subroutine sumw_1(w1, w2, wout) +c +c Sum two currents standing for the same off shell line: the four +c gluon current and the pair of three gluon vertices it factorises +c into carry the same colour factor, so the amplitude reading the sum +c gets both contributions from a single call. See +c HelasMatrixElement.get_quartic_current_sums. +c +c The two share their momentum, so only the wavefunction is added and +c everything else is taken over from the first one. +c + use ALOHA_OBJECT + implicit none + type(aloha) w1 + type(aloha) w2 + type(aloha) wout + + wout = w1 + wout%W(:) = w1%W(:) + w2%W(:) + + return + end + + + subroutine subw_1(w1, w2, wout) +c +c As sumw_1, for the contributions which enter with a minus sign. +c + use ALOHA_OBJECT + implicit none + type(aloha) w1 + type(aloha) w2 + type(aloha) wout + + wout = w1 + wout%W(:) = w1%W(:) - w2%W(:) + + return + end diff --git a/madgraph/core/helas_objects.py b/madgraph/core/helas_objects.py index fd70d6a8b5..0f3e3f2090 100755 --- a/madgraph/core/helas_objects.py +++ b/madgraph/core/helas_objects.py @@ -6267,6 +6267,9 @@ def compute_quartic_current_sums(self): unrollable, cubic_ids) if not pairs: continue + # the sum is written with sumw_1 / subw_1, which carry no weight + if abs(coeff) != 1: + continue # the quartic current has to be there when the target is written if any(quartic.get('number') not in available[target] for cubic, quartic in pairs): diff --git a/madgraph/iolibs/helas_call_writers.py b/madgraph/iolibs/helas_call_writers.py index 6873bcd26f..27d1230ec7 100755 --- a/madgraph/iolibs/helas_call_writers.py +++ b/madgraph/iolibs/helas_call_writers.py @@ -1130,22 +1130,18 @@ def get_current_sum_lines(self, number, cubic, quartic, coeff): """Sum the quartic current into the cubic one carrying the same colour factor, so that the amplitude reading the sum gets both at once. - The two share their momentum, so only the wavefunction itself is - added; everything else is taken over from the cubic current.""" - - out = self.format_helas_object('W(', '%d') % number - from_cubic = self.format_helas_object('W(', '%d') % cubic.get('me_id') - from_quartic = self.format_helas_object('W(', '%d') % \ - quartic.get('me_id') - - if coeff == 1: - added = '%s%%W(:)' % from_quartic - elif coeff == -1: - added = '-%s%%W(:)' % from_quartic - else: - added = '(%.15e)*%s%%W(:)' % (float(coeff), from_quartic) - return ['%s = %s' % (out, from_cubic), - '%s%%W(:) = %s%%W(:) + %s' % (out, from_cubic, added)] + Written as a call rather than as two assignments so that everything + reading these files -- the helicity recycling in particular, which + rebuilds the DAG from the calls alone -- sees an ordinary internal + wavefunction taking two mothers. sumw_1 and subw_1 live in + aloha_functions.f; the coefficient is always +-1, see + HelasMatrixElement.compute_quartic_current_sums.""" + + return ['CALL %s(%s,%s,%s)' % ( + 'SUMW_1' if coeff == 1 else 'SUBW_1', + self.format_helas_object('W(', '%d') % cubic.get('me_id'), + self.format_helas_object('W(', '%d') % quartic.get('me_id'), + self.format_helas_object('W(', '%d') % number)] def __init__(self, argument={}, hel_sum = False, options={}): """Allow generating a HelasCallWriter from a Model.The hel_sum argument diff --git a/madgraph/madevent/hel_recycle.py b/madgraph/madevent/hel_recycle.py index af0a1e7daa..4dabf25569 100755 --- a/madgraph/madevent/hel_recycle.py +++ b/madgraph/madevent/hel_recycle.py @@ -497,8 +497,12 @@ def add_amp_index(self, matchobj): def add_indices(self, line): '''Add loop_var index to amp and output variable. Also update name of output variable.''' - # Doesnt work if the AMP arguments contain brackets - new_line = re.sub(r'\WAMP\(.*?\)', self.add_amp_index, line) + # Doesnt work if the AMP arguments contain brackets. + # The character in front is looked at rather than eaten, so that an + # AMP( opening the statement is indexed too -- which is what a line + # like "AMP(31) = AMP(31) + AMP(1)" needs. + new_line = re.sub(r'(? Date: Wed, 5 Aug 2026 08:26:30 +0200 Subject: [PATCH 14/39] record the madevent port and what it does to AMP2 The interesting part is not the matrix element speedup but the channel weights: get_amp2_lines skips any diagram with a four point vertex, so with the flag off four fifths of the amplitude at six gluons -- 405 of 510 pieces -- entered no AMP2 at all. Folding puts each of them in the channel whose colour factor it shares. Co-Authored-By: Claude Opus 5 --- docs/gluon-quartic-plan.md | 48 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/docs/gluon-quartic-plan.md b/docs/gluon-quartic-plan.md index 7b00f4079f..76d02323b8 100644 --- a/docs/gluon-quartic-plan.md +++ b/docs/gluon-quartic-plan.md @@ -216,6 +216,54 @@ unchanged for `g g > t t~ g g` and `u u~ > g g g`. With the flag off, `matrix.f` is byte-identical to `3b3ed9e85` for N=2..5. +## Step 6 — madevent, and what it does to AMP2 + +`29b0c670e`. Two things had to give before the optimisation survived the +madevent path, neither of them about AMP2: + +1. **The sum has to be a `CALL`.** Helicity recycling rebuilds the whole DAG + from the calls alone, so a bare assignment was invisible to it — the summed + current never entered the graph and the amplitude reading it died on a + `KeyError`. Written as `CALL SUMW_1(W(a),W(b),W(c))` it is an ordinary + internal wavefunction with two mothers and everything downstream handles + it. `sumw_1`/`subw_1` live in `aloha_functions.f`; the coefficient is + restricted to ±1, which is all it has ever been. +2. **`hel_recycle.add_indices` could not index a statement-initial `AMP(`.** + The pattern ate the character in front of it and there is none at the + start of a line, so `AMP(31) = AMP(31) + AMP(1)` came out as + `AMP(31) = AMP( K,31) + AMP( K,1)`. Latent until now: nothing had ever + emitted a line beginning with `AMP(`. + +**AMP2 is left alone and picks up the merged amplitude**, which is the right +thing and turns out to matter more than the matrix element speedup. The fold +lines run before the AMP2 block, so the channel weight is +`|AMP_cubic + AMP_quartic|^2`. Nothing else was needed: `get_amp2_lines` +already skips any diagram with a four point vertex, so the folded amplitudes +were never referenced. + +That skip is the point. With the flag off, at six gluons: + +| | amplitudes computed | distinct AMP reaching AMP2 | +|---|---|---| +| flag off | 510 | **105** | +| flag on | 450 (+30 sums) | 105, now carrying all 510 | + +so four fifths of the amplitude — every quartic contribution — used to enter +**no** channel weight at all. Folding puts each of them in the channel whose +colour factor it shares, which is exactly where it belongs. + +`g g > g g g` through madevent, 10000 events, three seeds: + +| | cross section | rel. error | ME cpu | +|---|---|---|---| +| flag off | 3.680-3.694e+07 pb | 0.326% | 52.7 s | +| flag on | 3.684-3.694e+07 pb | 0.300% | 49.0 s | + +8% less error for 7% less cpu, consistently across the three seeds. At six +gluons the end-to-end runs are far noisier — the refine stage adapts, and the +same configuration swings by a factor two between seeds — so that comparison +needs a fixed-work measurement rather than `generate_events` wall time. + ## Where to go next What is left is the sums which do not sit at an amplitude, and they need a From ceba0c485d3cf8b44a2e6f2f0921407b5f3f39cf Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 08:48:53 +0200 Subject: [PATCH 15/39] measure the integration both ways: no effect either side The four gluon contributions now reach AMP2 -- 510 amplitude pieces instead of 105 at six gluons -- and the question was whether that helps or hurts the phase space integration. It does neither, measurably. generate_events wall time turned out to be a bad metric: the refine stage adapts, and the same configuration swings by a factor four between seeds (217 s to 877 s with the flag off at six gluons). Adding a survey only run -- the same fixed number of points both ways, so the error measures the channel weights and nothing else -- and quoting standard errors over independent seeds settles it: off - on significance g g > g g g error (3 seeds) -8% 1.8 sigma g g > g g g cpu (3 seeds) -7% 1.1 sigma g g > g g g g survey error (6) -10% 1.1 sigma g g > g g g g full error (4) -5% 0.8 sigma g g > g g g g full cpu (4) -1% 0.0 sigma Every difference points the same way and none of them is established. Cross sections agree throughout. Calling it either way would need tens of seeds. Co-Authored-By: Claude Opus 5 --- docs/gluon-quartic-plan.md | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/docs/gluon-quartic-plan.md b/docs/gluon-quartic-plan.md index 76d02323b8..b2e6197446 100644 --- a/docs/gluon-quartic-plan.md +++ b/docs/gluon-quartic-plan.md @@ -252,17 +252,43 @@ so four fifths of the amplitude — every quartic contribution — used to enter **no** channel weight at all. Folding puts each of them in the channel whose colour factor it shares, which is exactly where it belongs. -`g g > g g g` through madevent, 10000 events, three seeds: +**The integration is not measurably better or worse.** That is the answer, and +it took some care to get to, because `generate_events` wall time is a bad +metric here: the refine stage adapts, and the *same* configuration swings by a +factor four between seeds (217 s to 877 s with the flag off). Every number +below is mean +- standard error over independent seeds. + +`g g > g g g`, `generate_events`, 10000 events, three seeds: | | cross section | rel. error | ME cpu | |---|---|---|---| -| flag off | 3.680-3.694e+07 pb | 0.326% | 52.7 s | +| flag off | 3.680-3.694e+07 pb | 0.327% | 52.7 s | | flag on | 3.684-3.694e+07 pb | 0.300% | 49.0 s | -8% less error for 7% less cpu, consistently across the three seeds. At six -gluons the end-to-end runs are far noisier — the refine stage adapts, and the -same configuration swings by a factor two between seeds — so that comparison -needs a fixed-work measurement rather than `generate_events` wall time. +`g g > g g g g`, `generate_events`, 2000 events, four seeds, and a survey-only +run — the same fixed number of points both ways, so the error measures the +channel weights and nothing else — over six seeds: + +| | rel. error (survey) | rel. error (full) | cpu (full) | +|---|---|---|---| +| flag off | 2.14% | 0.498% | 583 s | +| flag on | 1.93% | 0.473% | 580 s | + +Every difference is favourable and none of them is significant: + +| | off - on | | +|---|---|---| +| `g g > g g g` error | -8% | 1.8 sigma | +| `g g > g g g` cpu | -7% | 1.1 sigma | +| `g g > g g g g` survey error | -10% | 1.1 sigma | +| `g g > g g g g` full error | -5% | 0.8 sigma | +| `g g > g g g g` full cpu | -1% | 0.0 sigma | + +Cross sections agree everywhere. So the honest reading is that handing the +quartic contributions to the channel that shares their colour factor does not +hurt the integration, and may help it slightly — but the seed to seed scatter +is far larger than the effect, and nothing here is established at more than +two sigma. A campaign of tens of seeds would be needed to call it either way. ## Where to go next From e93dfa1b110433d4d01c19b409972c00eaf8ca60 Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 09:26:39 +0200 Subject: [PATCH 16/39] carry the current sum into madmatrix SUMW_1/SUBW_1 as C++ templates next to ALOHAOBJ in cpp_hel_amps_h.inc, and the madmatrix helas call writer emits them the same way the Fortran one does -- as soon as the later of the two currents is made -- and skips the amplitudes they take away. They cannot use the INLINE macro: that is defined by the ALOHA generated block further down the header. The colour amplitudes had to be sorted out first, and this fixes a real bug rather than adding a feature. get_color_amplitudes dropped every merge source from the JAMPs, on the assumption that the caller writes out the amplitude sums to put them back. Only the Fortran writer does that, so C++ and python output with MG_MERGE_QUARTIC set was quietly losing four fifths of the amplitude. It now takes merge_quartic_amplitudes, and a backend which writes no sums keeps those amplitudes in the JAMPs, where their own colour coefficients give the identical result -- the two carry the same colour factor, which is the whole premise. So madmatrix gets the current sums, which really do remove work, and leaves the rest alone. One bug found on the way, in the shared writer: a wavefunction number can be listed by more than one diagram in the madmatrix matrix element (two objects for the same current with the mothers ordered differently), so the sum was written twice -- 50 lines for 30 sums at six gluons. Harmless numerically, both write the same value to the same slot, but wasted. Both writers now write each sum once. |M|^2, FPTYPE=d, against the same output without the flag: g g > g g g 1.8740711159594241e-02 vs ...317e-02 g g > g g g g 1.5929925846563324e-04 vs ...478e-04 and byte-identical CPPProcess.cc with the flag off. Speed is mixed, and worse than Fortran: amp calls nwf evt/s (FPTYPE=d, sse4) g g > g g g 45 -> 38 12 -> 26 72950 -> 66800 -8.4% g g > g g g g 510 -> 450 51 -> 111 2702 -> 2726 +0.9% The wavefunction array more than doubles, because the sums take a slot each at the end and are never recycled, and there is no JAMP fold here to pay for it. At five gluons that loses outright. Recycling the sum slots through reuse_outdated_wavefunctions is the obvious next step. Co-Authored-By: Claude Opus 5 --- UNITTEST_proc/Source/DHELAS/aloha_functions.f | 40 ++++++++++++++++ madgraph/core/helas_objects.py | 23 +++++++--- madgraph/iolibs/export_cpp.py | 7 +-- madgraph/iolibs/export_python.py | 5 +- madgraph/iolibs/helas_call_writers.py | 6 +++ .../madmatrix/cpp_hel_amps_h.inc | 33 +++++++++++++ madmatrix/model_handling.py | 46 ++++++++++++++++++- 7 files changed, 148 insertions(+), 12 deletions(-) diff --git a/UNITTEST_proc/Source/DHELAS/aloha_functions.f b/UNITTEST_proc/Source/DHELAS/aloha_functions.f index 46561ce7d9..8d558bbe0b 100644 --- a/UNITTEST_proc/Source/DHELAS/aloha_functions.f +++ b/UNITTEST_proc/Source/DHELAS/aloha_functions.f @@ -3042,3 +3042,43 @@ subroutine olxxxx(p,ffmass,nhel,nsf,fo) c return end + + subroutine sumw_1(w1, w2, wout) +c +c Sum two currents standing for the same off shell line: the four +c gluon current and the pair of three gluon vertices it factorises +c into carry the same colour factor, so the amplitude reading the sum +c gets both contributions from a single call. See +c HelasMatrixElement.get_quartic_current_sums. +c +c The two share their momentum, so only the wavefunction is added and +c everything else is taken over from the first one. +c + use ALOHA_OBJECT + implicit none + type(aloha) w1 + type(aloha) w2 + type(aloha) wout + + wout = w1 + wout%W(:) = w1%W(:) + w2%W(:) + + return + end + + + subroutine subw_1(w1, w2, wout) +c +c As sumw_1, for the contributions which enter with a minus sign. +c + use ALOHA_OBJECT + implicit none + type(aloha) w1 + type(aloha) w2 + type(aloha) wout + + wout = w1 + wout%W(:) = w1%W(:) - w2%W(:) + + return + end diff --git a/madgraph/core/helas_objects.py b/madgraph/core/helas_objects.py index 0f3e3f2090..ce68d17aaa 100755 --- a/madgraph/core/helas_objects.py +++ b/madgraph/core/helas_objects.py @@ -6129,20 +6129,29 @@ def generate_color_amplitudes(self, color_basis, diagrams): return col_amp_list - def get_color_amplitudes(self): + def get_color_amplitudes(self, merge_quartic_amplitudes=True): """Return a list of (coefficient, amplitude number) lists, corresponding to the JAMPs for this matrix element. The coefficients are given in the format (fermion factor, color - coeff (frac), imaginary, Nc power).""" + coeff (frac), imaginary, Nc power). + + merge_quartic_amplitudes says whether the caller also writes out the + sums of get_quartic_amplitude_merges. Only the Fortran writer does. + A backend which does not has to leave those amplitudes in the JAMPs, + where their own colour coefficients give the identical result -- the + two carry the same colour factor, which is the whole premise.""" col_amps = self.generate_color_amplitudes(self['color_basis'], self['diagrams']) - merges = self.get_quartic_amplitude_merges() - if not merges: + # never computed at all: their current was summed instead + dropped = set(self.get_quartic_current_sums()[2]) + if merge_quartic_amplitudes: + # summed into their partner by GET_AMP, so they must not enter the + # JAMPs a second time + dropped |= set(self.get_quartic_amplitude_merges()) + if not dropped: return col_amps - # These have been summed into their partner by GET_AMP already, so - # they must not enter the JAMPs a second time. - return [[entry for entry in col_amp if entry[1] not in merges] + return [[entry for entry in col_amp if entry[1] not in dropped] for col_amp in col_amps] def get_quartic_amplitude_merges(self): diff --git a/madgraph/iolibs/export_cpp.py b/madgraph/iolibs/export_cpp.py index 354815b369..bd26638f10 100755 --- a/madgraph/iolibs/export_cpp.py +++ b/madgraph/iolibs/export_cpp.py @@ -967,7 +967,8 @@ def get_process_class_definitions(self, write=True): replace_dict['nprocesses'] = self.nprocesses - color_amplitudes = self.matrix_elements[0].get_color_amplitudes() + color_amplitudes = self.matrix_elements[0].get_color_amplitudes( + merge_quartic_amplitudes=False) # Number of color flows replace_dict['ncolor'] = len(color_amplitudes) @@ -1045,7 +1046,7 @@ def get_process_function_definitions(self, write=True): # Extract process class name (for the moment same as file name) replace_dict['process_class_name'] = self.process_name - color_amplitudes = [me.get_color_amplitudes() for me in \ + color_amplitudes = [me.get_color_amplitudes(merge_quartic_amplitudes=False) for me in \ self.matrix_elements] replace_dict['initProc_lines'] = \ @@ -2124,7 +2125,7 @@ def get_process_function_definitions(self, write=True): # Extract process class name (for the moment same as file name) replace_dict['process_class_name'] = self.process_name - color_amplitudes = [me.get_color_amplitudes() for me in \ + color_amplitudes = [me.get_color_amplitudes(merge_quartic_amplitudes=False) for me in \ self.matrix_elements] replace_dict['initProc_lines'] = \ diff --git a/madgraph/iolibs/export_python.py b/madgraph/iolibs/export_python.py index 2b1ee59244..7b438024fc 100755 --- a/madgraph/iolibs/export_python.py +++ b/madgraph/iolibs/export_python.py @@ -243,7 +243,10 @@ def get_jamp_lines(self, matrix_element): res_list = [] - for i, coeff_list in enumerate(matrix_element.get_color_amplitudes()): + # this writer emits no amplitude sums, so the quartic contributions + # have to stay in the JAMPs with their own colour coefficients + for i, coeff_list in enumerate(matrix_element.get_color_amplitudes( + merge_quartic_amplitudes=False)): res = "jamp[%d] = " % i diff --git a/madgraph/iolibs/helas_call_writers.py b/madgraph/iolibs/helas_call_writers.py index 27d1230ec7..86b1b64b24 100755 --- a/madgraph/iolibs/helas_call_writers.py +++ b/madgraph/iolibs/helas_call_writers.py @@ -243,12 +243,18 @@ def get_matrix_element_calls(self, matrix_element): []).append(i) res = [] + written = set() for diagram in matrix_element.get('diagrams'): for wf in diagram.get('wavefunctions'): res.append(self.get_wavefunction_call(wf)) for i in after.get(wf.get('number'), []): + # a wavefunction number can be listed by more than one + # diagram, and the sum must only be written once + if i in written: + continue + written.add(i) cubic, quartic, coeff = sums[i] res.extend(self.get_current_sum_lines( first_sum + 1 + i, cubic, quartic, coeff)) diff --git a/madgraph/iolibs/template_files/madmatrix/cpp_hel_amps_h.inc b/madgraph/iolibs/template_files/madmatrix/cpp_hel_amps_h.inc index 8dde0fff4b..bed053192e 100644 --- a/madgraph/iolibs/template_files/madmatrix/cpp_hel_amps_h.inc +++ b/madgraph/iolibs/template_files/madmatrix/cpp_hel_amps_h.inc @@ -48,6 +48,39 @@ namespace mg5amcCpu : pvec(pvec_sv), w(reinterpret_cast(w_sv)), flv_index(flv) {} }; + // Sum two currents standing for the same off shell line: the four gluon + // current and the pair of three gluon vertices it factorises into carry the + // same colour factor, so the amplitude reading the sum gets both + // contributions from a single call. See + // HelasMatrixElement.get_quartic_current_sums. The two share their momentum, + // so only the wavefunction is added and the rest is taken from the first. + template + __device__ inline void + SUMW_1( const ALOHAOBJ& V2, const ALOHAOBJ& V3, ALOHAOBJ& V1 ) + { + const cxtype_sv* wV2 = W_ACCESS::kernelAccessConst( V2.w ); + const cxtype_sv* wV3 = W_ACCESS::kernelAccessConst( V3.w ); + cxtype_sv* wV1 = W_ACCESS::kernelAccess( V1.w ); + for( int i = 0; i < ALOHAOBJ::np4; i++ ) V1.pvec[i] = V2.pvec[i]; + for( int i = 0; i < ALOHAOBJ::nw6; i++ ) wV1[i] = wV2[i] + wV3[i]; + V1.flv_index = V2.flv_index; + return; + } + + // As SUMW_1, for the contributions which enter with a minus sign. + template + __device__ inline void + SUBW_1( const ALOHAOBJ& V2, const ALOHAOBJ& V3, ALOHAOBJ& V1 ) + { + const cxtype_sv* wV2 = W_ACCESS::kernelAccessConst( V2.w ); + const cxtype_sv* wV3 = W_ACCESS::kernelAccessConst( V3.w ); + cxtype_sv* wV1 = W_ACCESS::kernelAccess( V1.w ); + for( int i = 0; i < ALOHAOBJ::np4; i++ ) V1.pvec[i] = V2.pvec[i]; + for( int i = 0; i < ALOHAOBJ::nw6; i++ ) wV1[i] = wV2[i] - wV3[i]; + V1.flv_index = V2.flv_index; + return; + } + struct FLV_COUPLING_VIEW { const int* const partner1; diff --git a/madmatrix/model_handling.py b/madmatrix/model_handling.py index b4d1bac787..fef7e7018a 100644 --- a/madmatrix/model_handling.py +++ b/madmatrix/model_handling.py @@ -1727,7 +1727,8 @@ def get_process_function_definitions(self, write=True): replace_dict['all_helicities'] = replace_dict['all_helicities'] .replace('helicities', 'tHel') replace_dict['all_flavors'] = self.get_flavor_matrix(self.matrix_elements[0]) replace_dict['all_flavors'] = replace_dict['all_flavors'].replace('flavors', 'tFlavors') - color_amplitudes = [me.get_color_amplitudes() for me in self.matrix_elements] # as in OneProcessExporterCPP.get_process_function_definitions + color_amplitudes = [me.get_color_amplitudes(merge_quartic_amplitudes=False) + for me in self.matrix_elements] # as in OneProcessExporterCPP.get_process_function_definitions replace_dict['ncolor'] = len(color_amplitudes[0]) # broken_symmetry_factor function: use the shared decay-aware symmetry # data (same as the Fortran / standalone_cpp exporters) instead of the @@ -2531,6 +2532,23 @@ def _guard_open(group_mask): # Emit the opening of an `if` guard for a non-full grouped mask. return 'if( ( 0x%xULL >> iflavor ) & 0x1ULL ) {' % group_mask + # OM - the four gluon optimisation (MG_MERGE_QUARTIC). A quartic + # current and the cubic current carrying the same colour factor are + # summed into a third one, which the amplitude reads instead, so that + # one call gets both contributions and the quartic amplitude is never + # computed. The sum is written as soon as the later of the two + # currents is made. Unlike Fortran there is no AMP array here, so the + # amplitudes which cannot be reached this way are simply left alone: + # their own colour coefficients put them in the right JAMPs, which is + # why get_color_amplitudes is asked not to drop them. + sums, sum_uses, sum_folded = matrix_element.get_quartic_current_sums() + first_sum = matrix_element.get_number_of_wavefunctions() - len(sums) + sum_written = set() + sum_after = {} + for isum, (cubic, quartic, coeff) in enumerate(sums): + sum_after.setdefault(max(cubic.get('number'), + quartic.get('number')), []).append(isum) + id_amp = 0 for diagram in matrix_element.get('diagrams'): ###print('DIAGRAM %3d: #wavefunctions=%3d, #diagrams=%3d' % @@ -2547,13 +2565,39 @@ def _guard_open(group_mask): res.append('}') else: res.append(call) + for isum in sum_after.get(wf.get('number'), []): + # a wavefunction number can be listed by more than one + # diagram here, and the sum must only be written once + if isum in sum_written: + continue + sum_written.add(isum) + cubic, quartic, coeff = sums[isum] + res.append('%s( aloha_obj[%d], aloha_obj[%d],' + ' aloha_obj[%d] );' + % ('SUMW_1' if coeff == 1 else 'SUBW_1', + cubic.get('me_id') - 1, + quartic.get('me_id') - 1, + first_sum + isum)) if len(diagram.get('wavefunctions')) == 0 : res.append('// (none)') # AV res.append('\n // Amplitude(s) for diagram number %d' % diagram.get('number')) for amplitude in diagram.get('amplitudes'): id_amp +=1 + if amplitude.get('number') in sum_folded: + continue # summed into another amplitude as a current namp = amplitude.get('number') amplitude.set('number', 1) + # OM - read the current sum in place of the cubic current it + # was built from, the same way the Fortran writer does + sum_original = [] + for mother in amplitude.get('mothers'): + isum = sum_uses.get(namp, {}).get(mother.get('number')) + if isum is None: + continue + sum_original.append((mother, mother.get('me_id'))) + mother.set('me_id', first_sum + 1 + isum) amp_block = [ self.get_amplitude_call(amplitude) ] # AV new: avoid format_call + for mother, me_id in sum_original: + mother.set('me_id', me_id) if id_amp in diag_to_config: ###res.append("if( channelId == %i ) numerators_sv += cxabs2( amp_sv[0] );" % diag_to_config[id_amp]) # BUG #472 ###res.append("if( channelId == %i ) numerators_sv += cxabs2( amp_sv[0] );" % id_amp) # wrong fix for BUG #472 From 1ae5c34f0fa11f7bfe4ca65d47dcd9e802f014cc Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 09:27:13 +0200 Subject: [PATCH 17/39] record the madmatrix port and the slot cost it exposes The sums take a wavefunction slot each at the end and are never recycled, which more than doubles NWAVEFUNCS. Fortran absorbs that because the JAMP fold pays for it; madmatrix has no such fold and loses 8.4% at five gluons. Recycling those slots is now the first item under where to go next. Co-Authored-By: Claude Opus 5 --- docs/gluon-quartic-plan.md | 53 +++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/docs/gluon-quartic-plan.md b/docs/gluon-quartic-plan.md index b2e6197446..a4e2768092 100644 --- a/docs/gluon-quartic-plan.md +++ b/docs/gluon-quartic-plan.md @@ -290,9 +290,60 @@ hurt the integration, and may help it slightly — but the seed to seed scatter is far larger than the effect, and nothing here is established at more than two sigma. A campaign of tens of seeds would be needed to call it either way. +## Step 7 — madmatrix + +`e93dfa1b1`. `SUMW_1`/`SUBW_1` as C++ templates next to `ALOHAOBJ` in +`cpp_hel_amps_h.inc` (they cannot use the `INLINE` macro, which the ALOHA +generated block defines further down the header), and the madmatrix writer +emits them exactly as the Fortran one does. + +**The colour amplitudes had to be sorted out first, and that was a live bug.** +`get_color_amplitudes` dropped every merge source from the JAMPs on the +assumption that the caller writes the amplitude sums to put them back. Only +the Fortran writer does, so C++ and python output with `MG_MERGE_QUARTIC` set +was quietly losing four fifths of the amplitude. It now takes +`merge_quartic_amplitudes`; a backend which writes no sums keeps those +amplitudes in the JAMPs, where their own colour coefficients give the +identical result. So madmatrix gets the current sums, which really do remove +work, and leaves the amplitude level merges alone — there is no `AMP` array +there to fold into anyway, each amplitude going straight into the JAMPs. + +One bug in the shared writer surfaced here: a wavefunction number can be +listed by more than one diagram in the madmatrix matrix element (two objects +for the same current with the mothers ordered differently), so a sum was +written twice — 50 lines for 30 sums at six gluons. Harmless numerically, both +write the same value to the same slot, but wasted. Both writers now write each +sum once. + +|M|^2 to 1e-14 at five and six gluons (`FPTYPE=d`; the default mixed +precision build rounds the two to the same value), `CPPProcess.cc` +byte-identical with the flag off. + +**Speed is mixed, and worse than Fortran:** + +| | amp calls | nwf | evt/s (sse4, FPTYPE=d) | | +|---|---|---|---|---| +| `g g > g g g` | 45 -> 38 | 12 -> 26 | 72950 -> 66800 | **-8.4%** | +| `g g > g g g g` | 510 -> 450 | 51 -> 111 | 2702 -> 2726 | **+0.9%** | + +The wavefunction array more than doubles, because the sums take a slot each at +the end and are never recycled, and there is no JAMP fold here to pay for it. +At five gluons that loses outright. Note the base slot count with the flag on +is worse in madmatrix than in Fortran too (81 against 61 at six gluons), +because its matrix element carries duplicate wavefunctions which confuse +`reuse_outdated_wavefunctions`. + ## Where to go next -What is left is the sums which do not sit at an amplitude, and they need a +**Recycle the slots the sums take.** Cheapest and now the most valuable: +`get_number_of_wavefunctions` hands each sum a slot at the end which is never +reused, so `NWAVEFUNCS` goes 51 -> 91 in Fortran and 51 -> 111 in madmatrix at +six gluons. That is what makes madmatrix lose 8.4% at five gluons. A sum is +written at a known point and dead after its last target amplitude, so a linear +scan over those lifetimes would fit them into a handful of slots — or, better, +feed them to `reuse_outdated_wavefunctions` as ordinary producers. + +Then there are the sums which do not sit at an amplitude, and they need a node to have exactly one rooting *per merge*, which a diagram list cannot give. Three ways on, in increasing size: From 5b421bc8008c8a86a8cf5e10b19318ff6f05b9ab Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 10:38:24 +0200 Subject: [PATCH 18/39] recycle the slots the current sums take Each sum used to get a wavefunction slot of its own at the end, never reused, which more than doubled NWAVEFUNCS and was what made madmatrix lose 8.4% at five gluons. A sum is an ordinary producer -- written as soon as the later of its two currents is made, dead after the last amplitude reading it -- so it can go through reuse_outdated_wavefunctions with everything else. It also lets the cubic current die at the sum rather than at the amplitude, since the amplitude no longer reads it. NWAVEFUNCS flag off own slots recycled g g > g g g 12 26 19 g g > g g g g 51 91 66 g g > g g g g (madmatrix) 51 111 86 One bug had to be fixed first, and it is not mine: the same wavefunction can be listed by more than one diagram in the madmatrix matrix element (two objects for the same current with the mothers ordered differently), and reuse_outdated_wavefunctions handed it a slot again on the second listing. The first one leaked, and once the sums shared the pool that was no longer harmless -- g g > g g g g came out 0.2% wrong. A wavefunction now takes one slot at its first appearance and keeps it until its last use. This changes nothing with the flag off: matrix.f and CPPProcess.cc are byte-identical for N=2..4 in both backends. |M|^2 unchanged: bit-identical at four and five gluons, 1e-14 at six, and the madevent run for g g > g g g gives the same cross section and error as before (3.666e+07 +- 1.058e+05 pb, seed 33). per-call time before after fortran, 6 gluons +3.8% +3.9% (the slot count was not the bottleneck) madmatrix, 5 gl. -8.4% -6.6% madmatrix, 6 gl. +0.9% +1.9% Co-Authored-By: Claude Opus 5 --- madgraph/core/helas_objects.py | 91 ++++++++++++++----- madgraph/iolibs/helas_call_writers.py | 10 +- madmatrix/model_handling.py | 6 +- .../core/test_diagram_generation.py | 10 +- 4 files changed, 83 insertions(+), 34 deletions(-) diff --git a/madgraph/core/helas_objects.py b/madgraph/core/helas_objects.py index ce68d17aaa..7943a2b6e5 100755 --- a/madgraph/core/helas_objects.py +++ b/madgraph/core/helas_objects.py @@ -4002,6 +4002,8 @@ def default_setup(self): self.quartic_amplitude_merges = None # Cache for get_quartic_current_sums(), same reason self.quartic_current_sums = None + # Slots the current sums were given by reuse_outdated_wavefunctions + self.quartic_sum_me_ids = None def filter(self, name, value): """Filter for valid diagram property values.""" @@ -4420,17 +4422,24 @@ def reuse_outdated_wavefunctions(self, helas_diagrams): for diag in helas_diagrams: for wf in diag['wavefunctions']: wf.set('me_id',wf.get('number')) + self.quartic_sum_me_ids = None # a fresh slot each, at the end return helas_diagrams - # A current sum is written out as soon as the later of the two - # currents it reads is made, so both have to still be there then -- - # which this analysis has no way of knowing on its own. - sums = self.get_quartic_current_sums()[0] + # A current sum is a line of its own, written as soon as the later of + # the two currents it reads is made, and read by the amplitudes it was + # built for. Giving it a key here lets it take a slot from the same + # pool as everything else, rather than one of its own at the end -- + # and lets the cubic current die at the sum rather than at the + # amplitude, since the amplitude no longer reads it. + sums, uses, folded = self.get_quartic_current_sums() read_after = {} - for cubic, quartic in [(entry[0], entry[1]) for entry in sums]: + for isum, (cubic, quartic, coeff) in enumerate(sums): read_after.setdefault(max(cubic.get('number'), - quartic.get('number')), []).append( - (cubic.get('number'), quartic.get('number'))) + quartic.get('number')), []).append(isum) + # keys for the sums, above every wavefunction number + offset = max([wf.get('number') for diag in helas_diagrams + for wf in diag['wavefunctions']] or [0]) + sum_key = lambda isum: offset + 1 + isum # First compute the first/last appearance of each wavefunctions # first takes the line number and return the id of the created wf @@ -4438,21 +4447,42 @@ def reuse_outdated_wavefunctions(self, helas_diagrams): last_lign={} first={} pos=0 + written = set() + allocated = set() for diag in helas_diagrams: for wf in diag['wavefunctions']: pos+=1 for wfin in wf.get('mothers'): last_lign[wfin.get('number')] = pos assert wfin.get('number') in list(first.values()) + # the same wavefunction can be listed by more than one + # diagram; it is written twice with the same value, so it owns + # one slot from its first appearance to its last use, and + # handing it a second one here would leak the first + if wf.get('number') in allocated: + continue + allocated.add(wf.get('number')) first[pos] = wf.get('number') - for cubic, quartic in read_after.get(wf.get('number'), []): - last_lign[cubic] = pos - last_lign[quartic] = pos + for isum in read_after.get(wf.get('number'), []): + if isum in written: + continue + written.add(isum) + pos+=1 + cubic, quartic, coeff = sums[isum] + last_lign[cubic.get('number')] = pos + last_lign[quartic.get('number')] = pos + first[pos] = sum_key(isum) for amp in diag['amplitudes']: pos+=1 + substitution = uses.get(amp.get('number'), {}) for wfin in amp.get('mothers'): - last_lign[wfin.get('number')] = pos - + isum = substitution.get(wfin.get('number')) + if isum is None: + last_lign[wfin.get('number')] = pos + else: + # this amplitude reads the sum, not the cubic current + last_lign[sum_key(isum)] = pos + # last takes the line number and return the last appearing wf at #that particular line last=collections.defaultdict(list) @@ -4481,7 +4511,9 @@ def reuse_outdated_wavefunctions(self, helas_diagrams): for diag in helas_diagrams: for wf in diag['wavefunctions']: wf.set('me_id', replace[wf.get('number')]) - + self.quartic_sum_me_ids = [replace[sum_key(isum)] + for isum in range(len(sums))] + return helas_diagrams def restore_original_wavefunctions(self): @@ -4494,7 +4526,8 @@ def restore_original_wavefunctions(self): for diag in helas_diagrams: for wf in diag['wavefunctions']: wf.set('me_id',wf.get('number')) - + self.quartic_sum_me_ids = None # a fresh slot each, at the end + return helas_diagrams @@ -5332,15 +5365,15 @@ def get_num_configs(self): def get_number_of_wavefunctions(self): """Gives the total number of wavefunctions for this ME""" - # the current sums get a slot each, at the end and never reused - extra = self.get_number_of_quartic_current_sums() + # a current sum can hold the highest slot of all + extra = self.get_quartic_sum_me_ids() out = max([wf.get('me_id') for wfs in self.get('diagrams') for wf in wfs.get('wavefunctions')]) if out: - return out + extra - return sum([ len(d.get('wavefunctions')) for d in \ - self.get('diagrams')]) + extra + return max([out] + extra) + return max([sum([ len(d.get('wavefunctions')) for d in \ + self.get('diagrams')])] + extra) def get_all_wavefunctions(self): """Gives a list of all wavefunctions for this ME""" @@ -6241,10 +6274,24 @@ def get_quartic_current_sums(self): self.quartic_current_sums = self.compute_quartic_current_sums() return self.quartic_current_sums - def get_number_of_quartic_current_sums(self): - """How many extra wavefunction slots the current sums need.""" + def get_quartic_sum_me_ids(self): + """Wavefunction slot of each current sum. - return len(self.get_quartic_current_sums()[0]) + reuse_outdated_wavefunctions hands them out of the same pool as the + wavefunctions themselves, so a sum lands in whatever slot happens to + be free. When the wavefunctions were not recycled they get a fresh + slot each, at the end.""" + + sums = self.get_quartic_current_sums()[0] + if not sums: + return [] + if self.quartic_sum_me_ids is not None: + return self.quartic_sum_me_ids + used = [wf.get('me_id') or wf.get('number') + for diagram in self.get('diagrams') + for wf in diagram.get('wavefunctions')] + base = max(used or [0]) + return [base + 1 + isum for isum in range(len(sums))] def compute_quartic_current_sums(self): """Work out the current sums, see get_quartic_current_sums.""" diff --git a/madgraph/iolibs/helas_call_writers.py b/madgraph/iolibs/helas_call_writers.py index 86b1b64b24..d5637a3366 100755 --- a/madgraph/iolibs/helas_call_writers.py +++ b/madgraph/iolibs/helas_call_writers.py @@ -236,7 +236,7 @@ def get_matrix_element_calls(self, matrix_element): # a slot is only handed on after its last use, and the cubic one is # still needed by the amplitude the sum is for. sums, uses, folded = self.get_quartic_current_sums(matrix_element) - first_sum = matrix_element.get_number_of_wavefunctions() - len(sums) + slots = matrix_element.get_quartic_sum_me_ids() after = {} for i, (cubic, quartic, coeff) in enumerate(sums): after.setdefault(max(cubic.get('number'), quartic.get('number')), @@ -257,7 +257,7 @@ def get_matrix_element_calls(self, matrix_element): written.add(i) cubic, quartic, coeff = sums[i] res.extend(self.get_current_sum_lines( - first_sum + 1 + i, cubic, quartic, coeff)) + slots[i], cubic, quartic, coeff)) res.append("# Amplitude(s) for diagram number %d" % \ diagram.get('number')) for amplitude in diagram.get('amplitudes'): @@ -265,7 +265,7 @@ def get_matrix_element_calls(self, matrix_element): # summed into another amplitude through a current sum continue res.append(self.get_amplitude_call_on_sums( - amplitude, uses.get(amplitude.get('number')), first_sum)) + amplitude, uses.get(amplitude.get('number')), slots)) res.extend(self.get_amplitude_merge_lines(matrix_element)) @@ -282,7 +282,7 @@ def get_current_sum_lines(self, number, cubic, quartic, coeff): raise NotImplementedError - def get_amplitude_call_on_sums(self, amplitude, substitution, first_sum): + def get_amplitude_call_on_sums(self, amplitude, substitution, slots): """The amplitude call, reading the current sums in place of the cubic currents they were built from. @@ -298,7 +298,7 @@ def get_amplitude_call_on_sums(self, amplitude, substitution, first_sum): if index is None: continue original.append((mother, mother.get('me_id'))) - mother.set('me_id', first_sum + 1 + index) + mother.set('me_id', slots[index]) try: return self.get_amplitude_call(amplitude) finally: diff --git a/madmatrix/model_handling.py b/madmatrix/model_handling.py index fef7e7018a..6f943285d8 100644 --- a/madmatrix/model_handling.py +++ b/madmatrix/model_handling.py @@ -2542,7 +2542,7 @@ def _guard_open(group_mask): # their own colour coefficients put them in the right JAMPs, which is # why get_color_amplitudes is asked not to drop them. sums, sum_uses, sum_folded = matrix_element.get_quartic_current_sums() - first_sum = matrix_element.get_number_of_wavefunctions() - len(sums) + sum_slots = matrix_element.get_quartic_sum_me_ids() sum_written = set() sum_after = {} for isum, (cubic, quartic, coeff) in enumerate(sums): @@ -2577,7 +2577,7 @@ def _guard_open(group_mask): % ('SUMW_1' if coeff == 1 else 'SUBW_1', cubic.get('me_id') - 1, quartic.get('me_id') - 1, - first_sum + isum)) + sum_slots[isum] - 1)) if len(diagram.get('wavefunctions')) == 0 : res.append('// (none)') # AV res.append('\n // Amplitude(s) for diagram number %d' % diagram.get('number')) for amplitude in diagram.get('amplitudes'): @@ -2594,7 +2594,7 @@ def _guard_open(group_mask): if isum is None: continue sum_original.append((mother, mother.get('me_id'))) - mother.set('me_id', first_sum + 1 + isum) + mother.set('me_id', sum_slots[isum]) amp_block = [ self.get_amplitude_call(amplitude) ] # AV new: avoid format_call for mother, me_id in sum_original: mother.set('me_id', me_id) diff --git a/tests/unit_tests/core/test_diagram_generation.py b/tests/unit_tests/core/test_diagram_generation.py index d1fc1d98c7..37685f980b 100755 --- a/tests/unit_tests/core/test_diagram_generation.py +++ b/tests/unit_tests/core/test_diagram_generation.py @@ -4238,8 +4238,7 @@ def test_current_sums_inactive_by_default(self): {'legs':myleglist, 'model':self.base_model}))) self.assertEqual(matrix_element.get_quartic_current_sums(), ([], {}, set())) - self.assertEqual( - matrix_element.get_number_of_quartic_current_sums(), 0) + self.assertEqual(matrix_element.get_quartic_sum_me_ids(), []) def check_current_sums(self, initial, final, nsum, nfolded): """A current sum has to stand for exactly the amplitude it takes away: @@ -4260,8 +4259,11 @@ def check_current_sums(self, initial, final, nsum, nfolded): merges = matrix_element.get_quartic_amplitude_merges() self.assertEqual(len(sums), nsum) self.assertEqual(len(folded), nfolded) - self.assertEqual(matrix_element.get_number_of_quartic_current_sums(), - nsum) + # every sum gets a wavefunction slot, out of the same pool as the + # wavefunctions themselves + slots = matrix_element.get_quartic_sum_me_ids() + self.assertEqual(len(slots), nsum) + self.assertTrue(all(slot > 0 for slot in slots)) amplitudes = dict((amplitude.get('number'), amplitude) for diagram in matrix_element.get('diagrams') From 5210b17152241455fbe5a8b79971132f87432181 Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 10:39:02 +0200 Subject: [PATCH 19/39] record the slot recycling and what is left for madmatrix Co-Authored-By: Claude Opus 5 --- docs/gluon-quartic-plan.md | 62 +++++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 17 deletions(-) diff --git a/docs/gluon-quartic-plan.md b/docs/gluon-quartic-plan.md index a4e2768092..749ac0aba4 100644 --- a/docs/gluon-quartic-plan.md +++ b/docs/gluon-quartic-plan.md @@ -319,29 +319,57 @@ sum once. precision build rounds the two to the same value), `CPPProcess.cc` byte-identical with the flag off. -**Speed is mixed, and worse than Fortran:** +**Speed is mixed, and worse than Fortran** (after step 8): | | amp calls | nwf | evt/s (sse4, FPTYPE=d) | | |---|---|---|---|---| -| `g g > g g g` | 45 -> 38 | 12 -> 26 | 72950 -> 66800 | **-8.4%** | -| `g g > g g g g` | 510 -> 450 | 51 -> 111 | 2702 -> 2726 | **+0.9%** | - -The wavefunction array more than doubles, because the sums take a slot each at -the end and are never recycled, and there is no JAMP fold here to pay for it. -At five gluons that loses outright. Note the base slot count with the flag on -is worse in madmatrix than in Fortran too (81 against 61 at six gluons), -because its matrix element carries duplicate wavefunctions which confuse -`reuse_outdated_wavefunctions`. +| `g g > g g g` | 45 -> 38 | 12 -> 19 | 72820 -> 68010 | **-6.6%** | +| `g g > g g g g` | 510 -> 450 | 51 -> 86 | 2696 -> 2748 | **+1.9%** | + +There is no JAMP fold here to pay for the extra wavefunctions, so five gluons +loses outright: 7 sums against 7 saved amplitude calls does not cover a +wavefunction array half again as large. Note the slot count with the flag on +is worse in madmatrix than in Fortran (86 against 66 at six gluons), because +its matrix element carries duplicate wavefunctions -- two objects for the same +current with the mothers ordered differently, which MG5 does not merge. + +## Step 8 — recycle the slots the sums take + +`5b421bc80`. A sum used to get a slot of its own at the end, never reused, +which more than doubled `NWAVEFUNCS`. But a sum is an ordinary producer -- +written as soon as the later of its two currents is made, dead after the last +amplitude reading it -- so it goes through `reuse_outdated_wavefunctions` with +everything else. That also lets the cubic current die at the sum rather than +at the amplitude, since the amplitude no longer reads it. + +| | flag off | own slots | recycled | +|---|---|---|---| +| `g g > g g g` | 12 | 26 | **19** | +| `g g > g g g g` | 51 | 91 | **66** | +| `g g > g g g g` (madmatrix) | 51 | 111 | **86** | + +**A bug in `reuse_outdated_wavefunctions` had to be fixed first, and it was +not introduced here.** The same wavefunction can be listed by more than one +diagram in the madmatrix matrix element, and the allocator handed it a slot +again on the second listing, leaking the first. Harmless while the sums had +their own slots; once they shared the pool, `g g > g g g g` came out 0.2% +wrong. A wavefunction now takes one slot at its first appearance and keeps it +until its last use. Nothing moves with the flag off -- `matrix.f` and +`CPPProcess.cc` are byte-identical for N=2..4 in both backends. + +Worth it for madmatrix (-8.4% -> -6.6% at five gluons, +0.9% -> +1.9% at six) +and neutral for Fortran (+3.8% -> +3.9%): there the slot count was never the +bottleneck. The madevent run is unchanged, same cross section and error. ## Where to go next -**Recycle the slots the sums take.** Cheapest and now the most valuable: -`get_number_of_wavefunctions` hands each sum a slot at the end which is never -reused, so `NWAVEFUNCS` goes 51 -> 91 in Fortran and 51 -> 111 in madmatrix at -six gluons. That is what makes madmatrix lose 8.4% at five gluons. A sum is -written at a known point and dead after its last target amplitude, so a linear -scan over those lifetimes would fit them into a handful of slots — or, better, -feed them to `reuse_outdated_wavefunctions` as ordinary producers. +**Give madmatrix the amplitude sums too.** It is the only backend without +them, because there is no `AMP` array to fold into — each amplitude goes +straight into the JAMPs. That is why it gains 1.9% where Fortran gains 3.9%, +and why five gluons still loses. The sources for one target could be +accumulated into a second `amp_sv` slot before the JAMP lines are written, +which the seed ordering makes possible (the quartic diagrams come first), at +the cost of one accumulator per open target. Then there are the sums which do not sit at an amplitude, and they need a node to have exactly one rooting *per merge*, which a diagram list cannot From 34486c09d736c7ea08d2ea56a7ee3a79bf1989a3 Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 11:22:54 +0200 Subject: [PATCH 20/39] measure memory and speed for g g > N g, N=2..5, in both backends The wavefunction store is what the optimisation costs and the JAMP block is what it buys, so both are tabulated against the multiplicity. Four gluons is a wash, five loses on madmatrix, six and seven win on both and the gain grows. The relative memory cost falls the other way, from +58% at five gluons to +8% at seven, which is why the trade turns positive. Co-Authored-By: Claude Opus 5 --- docs/gluon-quartic-plan.md | 53 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/docs/gluon-quartic-plan.md b/docs/gluon-quartic-plan.md index 749ac0aba4..121a55728b 100644 --- a/docs/gluon-quartic-plan.md +++ b/docs/gluon-quartic-plan.md @@ -361,6 +361,59 @@ Worth it for madmatrix (-8.4% -> -6.6% at five gluons, +0.9% -> +1.9% at six) and neutral for Fortran (+3.8% -> +3.9%): there the slot count was never the bottleneck. The madevent run is unchanged, same cross section and error. +## Results + +Everything below is `g g > N g` with `MG_MERGE_QUARTIC` off against on, on the +same machine. Standalone Fortran is the shipped `check` driver looping +`SMATRIX`; madmatrix is `check_sa.exe perf` built `FPTYPE=d` on `cppsse4` +(the default mixed precision build rounds the two to the same value and would +hide any difference). Two runs each, reproducible to about 0.1%. + +**Speed** + +| | standalone | | madmatrix | | +|---|---|---|---|---| +| | per call | | evt/s | | +| `g g > g g` | 11.00 -> 11.04 s | -0.4% | 875150 -> 878724 | +0.4% | +| `g g > g g g` | 34.90 -> 34.99 s | -0.3% | 72359 -> 66757 | **-7.7%** | +| `g g > g g g g` | 47.35 -> 45.61 s | **+3.7%** | 2699 -> 2784 | **+3.1%** | +| `g g > 5 g` | 43.05 -> 39.98 s | **+7.1%** | not measured | | + +Four gluons is a wash on both (there is nothing to sum: the only quartic +vertex is the whole amplitude). Five gluons loses on madmatrix, where the +wavefunction store grows by half and there is no JAMP fold to pay for it. Six +and seven gluons win on both, and the gain grows with the multiplicity. + +**Memory — the wavefunction store**, which is what the optimisation costs. +`NWAVEFUNCS` in Fortran, `nwf` in madmatrix; bytes are 100 per wavefunction in +Fortran (4 complex, 4 reals, one int) and 192 in madmatrix on sse4 in double +(4 complex plus a 4-momentum, over a 2 event vector). + +| | off | on, slot each | on, recycled | | +|---|---|---|---|---| +| `g g > g g` | 5 | 5 | 5 | 500 B | +| `g g > g g g` | 12 | 26 | **19** | 1900 B (+58%) | +| `g g > g g g g` | 51 | 91 | **66** | 6600 B (+29%) | +| `g g > 5 g` | 268 | 321 | **290** | 29000 B (+8%) | + +madmatrix carries duplicate wavefunctions of its own, so its count with the +flag on is higher: 19 / 86 at five and six gluons, against 19 / 66 in Fortran. +The relative cost falls as the multiplicity rises, which is why the trade +turns positive from six gluons on. + +**Work done per call** + +| | standalone helas calls | JAMP lines | madmatrix amplitude calls | jamp lines | +|---|---|---|---|---| +| `g g > g g` | 29 -> 29 | 23 -> 20 | 6 -> 6 | 34 -> 34 | +| `g g > g g g` | 94 -> 100 (+7 sums) | 131 -> 101 | 45 -> 38 | 370 -> 314 | +| `g g > g g g g` | 637 -> 642 (+30) | 1082 -> 688 | 510 -> 450 | 8170 -> 7210 | +| `g g > 5 g` | 8159 -> 7844 (+60) | 23672 -> 7864 | | | + +`|M|^2` is bit-identical at four and five gluons and agrees to 1e-14 at six +and seven, in both backends. With the flag off, `matrix.f` and `CPPProcess.cc` +are byte-identical to before any of this. + ## Where to go next **Give madmatrix the amplitude sums too.** It is the only backend without From fefb1159be8915ec97e3ba88a4ff959041b9b16c Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 11:24:14 +0200 Subject: [PATCH 21/39] drop the unit test output that got committed by mistake UNITTEST_proc is what ./tests/test_manager.py leaves behind; two commits picked it up through git add -A. Removed and added to .gitignore so it cannot happen again. Co-Authored-By: Claude Opus 5 --- .gitignore | 3 + UNITTEST_proc/Cards/MadLoopParams.dat | 298 -- UNITTEST_proc/Cards/MadLoopParams_default.dat | 298 -- UNITTEST_proc/Cards/ident_card.dat | 35 - UNITTEST_proc/Cards/param_card.dat | 93 - UNITTEST_proc/Cards/param_card_default.dat | 93 - UNITTEST_proc/MGMEVersion.txt | 1 - UNITTEST_proc/Source/DHELAS/FFV1LP0_3.f | 29 - UNITTEST_proc/Source/DHELAS/FFV1L_1.f | 51 - UNITTEST_proc/Source/DHELAS/FFV1L_2.f | 51 - UNITTEST_proc/Source/DHELAS/FFV1P0_3.f | 40 - UNITTEST_proc/Source/DHELAS/FFV1_0.f | 33 - UNITTEST_proc/Source/DHELAS/FFV1_1.f | 55 - UNITTEST_proc/Source/DHELAS/FFV1_2.f | 55 - UNITTEST_proc/Source/DHELAS/GHGHGL_1.f | 25 - UNITTEST_proc/Source/DHELAS/GHGHGL_2.f | 25 - UNITTEST_proc/Source/DHELAS/MP_FFV1LP0_3.f | 29 - UNITTEST_proc/Source/DHELAS/MP_FFV1L_1.f | 51 - UNITTEST_proc/Source/DHELAS/MP_FFV1L_2.f | 51 - UNITTEST_proc/Source/DHELAS/MP_FFV1P0_3.f | 40 - UNITTEST_proc/Source/DHELAS/MP_FFV1_0.f | 33 - UNITTEST_proc/Source/DHELAS/MP_FFV1_1.f | 55 - UNITTEST_proc/Source/DHELAS/MP_FFV1_2.f | 55 - UNITTEST_proc/Source/DHELAS/MP_GHGHGL_1.f | 25 - UNITTEST_proc/Source/DHELAS/MP_GHGHGL_2.f | 25 - UNITTEST_proc/Source/DHELAS/MP_R2_GG_1_0.f | 24 - .../Source/DHELAS/MP_R2_GG_1_R2_GG_2_0.f | 31 - .../Source/DHELAS/MP_R2_GG_1_R2_GG_3_0.f | 25 - UNITTEST_proc/Source/DHELAS/MP_R2_GG_2_0.f | 25 - UNITTEST_proc/Source/DHELAS/MP_R2_GG_3_0.f | 20 - UNITTEST_proc/Source/DHELAS/MP_R2_QQ_1_0.f | 33 - .../Source/DHELAS/MP_R2_QQ_1_R2_QQ_2_0.f | 37 - UNITTEST_proc/Source/DHELAS/MP_R2_QQ_2_0.f | 28 - UNITTEST_proc/Source/DHELAS/MP_VVV1LP0_1.f | 49 - UNITTEST_proc/Source/DHELAS/MP_VVV1P0_1.f | 52 - UNITTEST_proc/Source/DHELAS/MP_VVV1_0.f | 53 - UNITTEST_proc/Source/DHELAS/MP_VVVV1LP0_1.f | 30 - UNITTEST_proc/Source/DHELAS/MP_VVVV3LP0_1.f | 30 - UNITTEST_proc/Source/DHELAS/MP_VVVV4LP0_1.f | 30 - UNITTEST_proc/Source/DHELAS/R2_GG_1_0.f | 24 - .../Source/DHELAS/R2_GG_1_R2_GG_2_0.f | 31 - .../Source/DHELAS/R2_GG_1_R2_GG_3_0.f | 25 - UNITTEST_proc/Source/DHELAS/R2_GG_2_0.f | 25 - UNITTEST_proc/Source/DHELAS/R2_GG_3_0.f | 20 - UNITTEST_proc/Source/DHELAS/R2_QQ_1_0.f | 33 - .../Source/DHELAS/R2_QQ_1_R2_QQ_2_0.f | 37 - UNITTEST_proc/Source/DHELAS/R2_QQ_2_0.f | 28 - UNITTEST_proc/Source/DHELAS/VVV1LP0_1.f | 49 - UNITTEST_proc/Source/DHELAS/VVV1P0_1.f | 52 - UNITTEST_proc/Source/DHELAS/VVV1_0.f | 53 - UNITTEST_proc/Source/DHELAS/VVVV1LP0_1.f | 30 - UNITTEST_proc/Source/DHELAS/VVVV3LP0_1.f | 30 - UNITTEST_proc/Source/DHELAS/VVVV4LP0_1.f | 30 - UNITTEST_proc/Source/DHELAS/aloha_file.inc | 1 - UNITTEST_proc/Source/DHELAS/aloha_functions.f | 3084 ----------------- UNITTEST_proc/Source/DHELAS/makefile | 40 - .../Source/MODEL/actualize_mp_ext_params.inc | 7 - UNITTEST_proc/Source/MODEL/coupl.inc | 47 - UNITTEST_proc/Source/MODEL/coupl_write.inc | 35 - UNITTEST_proc/Source/MODEL/couplings.f | 158 - UNITTEST_proc/Source/MODEL/couplings1.f | 16 - UNITTEST_proc/Source/MODEL/couplings2.f | 16 - UNITTEST_proc/Source/MODEL/couplings3.f | 68 - UNITTEST_proc/Source/MODEL/flavor_couplings.f | 30 - UNITTEST_proc/Source/MODEL/formats.inc | 30 - UNITTEST_proc/Source/MODEL/get_color.f | 158 - UNITTEST_proc/Source/MODEL/input.inc | 44 - .../Source/MODEL/intparam_definition.inc | 196 -- UNITTEST_proc/Source/MODEL/lha_read.f | 486 --- UNITTEST_proc/Source/MODEL/makefile | 56 - UNITTEST_proc/Source/MODEL/makeinc.inc | 5 - UNITTEST_proc/Source/MODEL/model_functions.f | 1038 ------ .../Source/MODEL/model_functions.inc | 32 - UNITTEST_proc/Source/MODEL/mp_coupl.inc | 44 - .../Source/MODEL/mp_coupl_same_name.inc | 37 - UNITTEST_proc/Source/MODEL/mp_couplings1.f | 16 - UNITTEST_proc/Source/MODEL/mp_couplings2.f | 16 - UNITTEST_proc/Source/MODEL/mp_couplings3.f | 80 - UNITTEST_proc/Source/MODEL/mp_input.inc | 56 - .../Source/MODEL/mp_intparam_definition.inc | 210 -- .../Source/MODEL/param_card_rule.dat | 25 - UNITTEST_proc/Source/MODEL/param_read.inc | 57 - UNITTEST_proc/Source/MODEL/param_write.inc | 100 - UNITTEST_proc/Source/MODEL/printout.f | 40 - UNITTEST_proc/Source/MODEL/rw_para.f | 97 - UNITTEST_proc/Source/MODEL/testprog.f | 72 - UNITTEST_proc/Source/coupl.inc | 1 - UNITTEST_proc/Source/make_opts | 132 - UNITTEST_proc/Source/makefile | 96 - .../ML5_0_ColorDenomFactors.dat | 129 - .../ML5_0_ColorNumFactors.dat | 129 - .../MadLoop5_resources/ML5_0_HelConfigs.dat | 16 - .../MadLoop5_resources/MadLoopParams.dat | 1 - .../MadLoop5_resources/ident_card.dat | 1 - .../MadLoop5_resources/param_card.dat | 1 - UNITTEST_proc/SubProcesses/MadLoopCommons.f | 682 ---- .../SubProcesses/MadLoopParamReader.f | 343 -- UNITTEST_proc/SubProcesses/MadLoopParams.dat | 1 - UNITTEST_proc/SubProcesses/MadLoopParams.inc | 30 - .../SubProcesses/MadLoop_makefile_definitions | 13 - .../SubProcesses/P0_gg_ttx/CT_interface.f | 663 ---- .../SubProcesses/P0_gg_ttx/MadLoop5_resources | 1 - .../SubProcesses/P0_gg_ttx/MadLoopCommons.f | 1 - .../P0_gg_ttx/MadLoopParamReader.f | 1 - .../SubProcesses/P0_gg_ttx/MadLoopParams.inc | 1 - .../SubProcesses/P0_gg_ttx/born_matrix.f | 989 ------ .../SubProcesses/P0_gg_ttx/born_matrix.ps | Bin 13824 -> 0 bytes .../SubProcesses/P0_gg_ttx/check_sa.f | 746 ---- .../SubProcesses/P0_gg_ttx/coupl.inc | 1 - .../SubProcesses/P0_gg_ttx/cts_mpc.h | 1 - .../SubProcesses/P0_gg_ttx/cts_mprec.h | 1 - .../SubProcesses/P0_gg_ttx/global_specs.inc | 1 - .../SubProcesses/P0_gg_ttx/improve_ps.f | 1014 ------ .../SubProcesses/P0_gg_ttx/loop_matrix.f | 1860 ---------- .../SubProcesses/P0_gg_ttx/loop_matrix.ps | Bin 46706 -> 0 bytes .../SubProcesses/P0_gg_ttx/loop_num.f | 934 ----- UNITTEST_proc/SubProcesses/P0_gg_ttx/makefile | 1 - .../SubProcesses/P0_gg_ttx/mg5_citation.f | 1 - .../P0_gg_ttx/mp_born_amps_and_wfs.f | 282 -- .../SubProcesses/P0_gg_ttx/mp_coupl.inc | 1 - .../P0_gg_ttx/mp_coupl_same_name.inc | 1 - .../SubProcesses/P0_gg_ttx/nexternal.inc | 4 - .../SubProcesses/P0_gg_ttx/ngraphs.inc | 2 - .../SubProcesses/P0_gg_ttx/nsquaredSO.inc | 2 - .../SubProcesses/P0_gg_ttx/pmass.inc | 4 - .../SubProcesses/P0_gg_ttx/unique_id.inc | 2 - UNITTEST_proc/SubProcesses/coupl.inc | 1 - UNITTEST_proc/SubProcesses/cts_mpc.h | 2 - UNITTEST_proc/SubProcesses/cts_mprec.h | 2 - UNITTEST_proc/SubProcesses/makefile | 201 -- UNITTEST_proc/SubProcesses/makefileP | 55 - UNITTEST_proc/SubProcesses/mg5_citation.f | 91 - UNITTEST_proc/SubProcesses/mp_coupl.inc | 1 - .../SubProcesses/mp_coupl_same_name.inc | 1 - UNITTEST_proc/TemplateVersion.txt | 1 - 135 files changed, 3 insertions(+), 17321 deletions(-) delete mode 100644 UNITTEST_proc/Cards/MadLoopParams.dat delete mode 100644 UNITTEST_proc/Cards/MadLoopParams_default.dat delete mode 100644 UNITTEST_proc/Cards/ident_card.dat delete mode 100644 UNITTEST_proc/Cards/param_card.dat delete mode 100644 UNITTEST_proc/Cards/param_card_default.dat delete mode 100644 UNITTEST_proc/MGMEVersion.txt delete mode 100644 UNITTEST_proc/Source/DHELAS/FFV1LP0_3.f delete mode 100644 UNITTEST_proc/Source/DHELAS/FFV1L_1.f delete mode 100644 UNITTEST_proc/Source/DHELAS/FFV1L_2.f delete mode 100644 UNITTEST_proc/Source/DHELAS/FFV1P0_3.f delete mode 100644 UNITTEST_proc/Source/DHELAS/FFV1_0.f delete mode 100644 UNITTEST_proc/Source/DHELAS/FFV1_1.f delete mode 100644 UNITTEST_proc/Source/DHELAS/FFV1_2.f delete mode 100644 UNITTEST_proc/Source/DHELAS/GHGHGL_1.f delete mode 100644 UNITTEST_proc/Source/DHELAS/GHGHGL_2.f delete mode 100644 UNITTEST_proc/Source/DHELAS/MP_FFV1LP0_3.f delete mode 100644 UNITTEST_proc/Source/DHELAS/MP_FFV1L_1.f delete mode 100644 UNITTEST_proc/Source/DHELAS/MP_FFV1L_2.f delete mode 100644 UNITTEST_proc/Source/DHELAS/MP_FFV1P0_3.f delete mode 100644 UNITTEST_proc/Source/DHELAS/MP_FFV1_0.f delete mode 100644 UNITTEST_proc/Source/DHELAS/MP_FFV1_1.f delete mode 100644 UNITTEST_proc/Source/DHELAS/MP_FFV1_2.f delete mode 100644 UNITTEST_proc/Source/DHELAS/MP_GHGHGL_1.f delete mode 100644 UNITTEST_proc/Source/DHELAS/MP_GHGHGL_2.f delete mode 100644 UNITTEST_proc/Source/DHELAS/MP_R2_GG_1_0.f delete mode 100644 UNITTEST_proc/Source/DHELAS/MP_R2_GG_1_R2_GG_2_0.f delete mode 100644 UNITTEST_proc/Source/DHELAS/MP_R2_GG_1_R2_GG_3_0.f delete mode 100644 UNITTEST_proc/Source/DHELAS/MP_R2_GG_2_0.f delete mode 100644 UNITTEST_proc/Source/DHELAS/MP_R2_GG_3_0.f delete mode 100644 UNITTEST_proc/Source/DHELAS/MP_R2_QQ_1_0.f delete mode 100644 UNITTEST_proc/Source/DHELAS/MP_R2_QQ_1_R2_QQ_2_0.f delete mode 100644 UNITTEST_proc/Source/DHELAS/MP_R2_QQ_2_0.f delete mode 100644 UNITTEST_proc/Source/DHELAS/MP_VVV1LP0_1.f delete mode 100644 UNITTEST_proc/Source/DHELAS/MP_VVV1P0_1.f delete mode 100644 UNITTEST_proc/Source/DHELAS/MP_VVV1_0.f delete mode 100644 UNITTEST_proc/Source/DHELAS/MP_VVVV1LP0_1.f delete mode 100644 UNITTEST_proc/Source/DHELAS/MP_VVVV3LP0_1.f delete mode 100644 UNITTEST_proc/Source/DHELAS/MP_VVVV4LP0_1.f delete mode 100644 UNITTEST_proc/Source/DHELAS/R2_GG_1_0.f delete mode 100644 UNITTEST_proc/Source/DHELAS/R2_GG_1_R2_GG_2_0.f delete mode 100644 UNITTEST_proc/Source/DHELAS/R2_GG_1_R2_GG_3_0.f delete mode 100644 UNITTEST_proc/Source/DHELAS/R2_GG_2_0.f delete mode 100644 UNITTEST_proc/Source/DHELAS/R2_GG_3_0.f delete mode 100644 UNITTEST_proc/Source/DHELAS/R2_QQ_1_0.f delete mode 100644 UNITTEST_proc/Source/DHELAS/R2_QQ_1_R2_QQ_2_0.f delete mode 100644 UNITTEST_proc/Source/DHELAS/R2_QQ_2_0.f delete mode 100644 UNITTEST_proc/Source/DHELAS/VVV1LP0_1.f delete mode 100644 UNITTEST_proc/Source/DHELAS/VVV1P0_1.f delete mode 100644 UNITTEST_proc/Source/DHELAS/VVV1_0.f delete mode 100644 UNITTEST_proc/Source/DHELAS/VVVV1LP0_1.f delete mode 100644 UNITTEST_proc/Source/DHELAS/VVVV3LP0_1.f delete mode 100644 UNITTEST_proc/Source/DHELAS/VVVV4LP0_1.f delete mode 100644 UNITTEST_proc/Source/DHELAS/aloha_file.inc delete mode 100644 UNITTEST_proc/Source/DHELAS/aloha_functions.f delete mode 100644 UNITTEST_proc/Source/DHELAS/makefile delete mode 100644 UNITTEST_proc/Source/MODEL/actualize_mp_ext_params.inc delete mode 100644 UNITTEST_proc/Source/MODEL/coupl.inc delete mode 100644 UNITTEST_proc/Source/MODEL/coupl_write.inc delete mode 100644 UNITTEST_proc/Source/MODEL/couplings.f delete mode 100644 UNITTEST_proc/Source/MODEL/couplings1.f delete mode 100644 UNITTEST_proc/Source/MODEL/couplings2.f delete mode 100644 UNITTEST_proc/Source/MODEL/couplings3.f delete mode 100644 UNITTEST_proc/Source/MODEL/flavor_couplings.f delete mode 100644 UNITTEST_proc/Source/MODEL/formats.inc delete mode 100644 UNITTEST_proc/Source/MODEL/get_color.f delete mode 100644 UNITTEST_proc/Source/MODEL/input.inc delete mode 100644 UNITTEST_proc/Source/MODEL/intparam_definition.inc delete mode 100644 UNITTEST_proc/Source/MODEL/lha_read.f delete mode 100644 UNITTEST_proc/Source/MODEL/makefile delete mode 100644 UNITTEST_proc/Source/MODEL/makeinc.inc delete mode 100644 UNITTEST_proc/Source/MODEL/model_functions.f delete mode 100644 UNITTEST_proc/Source/MODEL/model_functions.inc delete mode 100644 UNITTEST_proc/Source/MODEL/mp_coupl.inc delete mode 100644 UNITTEST_proc/Source/MODEL/mp_coupl_same_name.inc delete mode 100644 UNITTEST_proc/Source/MODEL/mp_couplings1.f delete mode 100644 UNITTEST_proc/Source/MODEL/mp_couplings2.f delete mode 100644 UNITTEST_proc/Source/MODEL/mp_couplings3.f delete mode 100644 UNITTEST_proc/Source/MODEL/mp_input.inc delete mode 100644 UNITTEST_proc/Source/MODEL/mp_intparam_definition.inc delete mode 100644 UNITTEST_proc/Source/MODEL/param_card_rule.dat delete mode 100644 UNITTEST_proc/Source/MODEL/param_read.inc delete mode 100644 UNITTEST_proc/Source/MODEL/param_write.inc delete mode 100644 UNITTEST_proc/Source/MODEL/printout.f delete mode 100644 UNITTEST_proc/Source/MODEL/rw_para.f delete mode 100644 UNITTEST_proc/Source/MODEL/testprog.f delete mode 120000 UNITTEST_proc/Source/coupl.inc delete mode 100644 UNITTEST_proc/Source/make_opts delete mode 100644 UNITTEST_proc/Source/makefile delete mode 100644 UNITTEST_proc/SubProcesses/MadLoop5_resources/ML5_0_ColorDenomFactors.dat delete mode 100644 UNITTEST_proc/SubProcesses/MadLoop5_resources/ML5_0_ColorNumFactors.dat delete mode 100644 UNITTEST_proc/SubProcesses/MadLoop5_resources/ML5_0_HelConfigs.dat delete mode 120000 UNITTEST_proc/SubProcesses/MadLoop5_resources/MadLoopParams.dat delete mode 120000 UNITTEST_proc/SubProcesses/MadLoop5_resources/ident_card.dat delete mode 120000 UNITTEST_proc/SubProcesses/MadLoop5_resources/param_card.dat delete mode 100644 UNITTEST_proc/SubProcesses/MadLoopCommons.f delete mode 100644 UNITTEST_proc/SubProcesses/MadLoopParamReader.f delete mode 120000 UNITTEST_proc/SubProcesses/MadLoopParams.dat delete mode 100644 UNITTEST_proc/SubProcesses/MadLoopParams.inc delete mode 100644 UNITTEST_proc/SubProcesses/MadLoop_makefile_definitions delete mode 100644 UNITTEST_proc/SubProcesses/P0_gg_ttx/CT_interface.f delete mode 120000 UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoop5_resources delete mode 120000 UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoopCommons.f delete mode 120000 UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoopParamReader.f delete mode 120000 UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoopParams.inc delete mode 100644 UNITTEST_proc/SubProcesses/P0_gg_ttx/born_matrix.f delete mode 100644 UNITTEST_proc/SubProcesses/P0_gg_ttx/born_matrix.ps delete mode 100644 UNITTEST_proc/SubProcesses/P0_gg_ttx/check_sa.f delete mode 120000 UNITTEST_proc/SubProcesses/P0_gg_ttx/coupl.inc delete mode 120000 UNITTEST_proc/SubProcesses/P0_gg_ttx/cts_mpc.h delete mode 120000 UNITTEST_proc/SubProcesses/P0_gg_ttx/cts_mprec.h delete mode 120000 UNITTEST_proc/SubProcesses/P0_gg_ttx/global_specs.inc delete mode 100644 UNITTEST_proc/SubProcesses/P0_gg_ttx/improve_ps.f delete mode 100644 UNITTEST_proc/SubProcesses/P0_gg_ttx/loop_matrix.f delete mode 100644 UNITTEST_proc/SubProcesses/P0_gg_ttx/loop_matrix.ps delete mode 100644 UNITTEST_proc/SubProcesses/P0_gg_ttx/loop_num.f delete mode 120000 UNITTEST_proc/SubProcesses/P0_gg_ttx/makefile delete mode 120000 UNITTEST_proc/SubProcesses/P0_gg_ttx/mg5_citation.f delete mode 100644 UNITTEST_proc/SubProcesses/P0_gg_ttx/mp_born_amps_and_wfs.f delete mode 120000 UNITTEST_proc/SubProcesses/P0_gg_ttx/mp_coupl.inc delete mode 120000 UNITTEST_proc/SubProcesses/P0_gg_ttx/mp_coupl_same_name.inc delete mode 100644 UNITTEST_proc/SubProcesses/P0_gg_ttx/nexternal.inc delete mode 100644 UNITTEST_proc/SubProcesses/P0_gg_ttx/ngraphs.inc delete mode 100644 UNITTEST_proc/SubProcesses/P0_gg_ttx/nsquaredSO.inc delete mode 100644 UNITTEST_proc/SubProcesses/P0_gg_ttx/pmass.inc delete mode 100644 UNITTEST_proc/SubProcesses/P0_gg_ttx/unique_id.inc delete mode 120000 UNITTEST_proc/SubProcesses/coupl.inc delete mode 100644 UNITTEST_proc/SubProcesses/cts_mpc.h delete mode 100644 UNITTEST_proc/SubProcesses/cts_mprec.h delete mode 100644 UNITTEST_proc/SubProcesses/makefile delete mode 100644 UNITTEST_proc/SubProcesses/makefileP delete mode 100644 UNITTEST_proc/SubProcesses/mg5_citation.f delete mode 120000 UNITTEST_proc/SubProcesses/mp_coupl.inc delete mode 120000 UNITTEST_proc/SubProcesses/mp_coupl_same_name.inc delete mode 100644 UNITTEST_proc/TemplateVersion.txt diff --git a/.gitignore b/.gitignore index e601b64224..dc672ea0b4 100644 --- a/.gitignore +++ b/.gitignore @@ -79,3 +79,6 @@ nsqso_born.inc docs/build/ tests/input_files/IOTestsComparison_BackUp/ tests/input_files/IOTestsComparison/**/*.BackUp + +# output of ./tests/test_manager.py +UNITTEST_proc/ diff --git a/UNITTEST_proc/Cards/MadLoopParams.dat b/UNITTEST_proc/Cards/MadLoopParams.dat deleted file mode 100644 index 425d909582..0000000000 --- a/UNITTEST_proc/Cards/MadLoopParams.dat +++ /dev/null @@ -1,298 +0,0 @@ -! This file is for the user to set the different parameters of MadLoop. -! The name of the variable to define must start with the '#' sign and then -! the value should be put immediately on the next line. - -! -#MLReductionLib -!6|7|1 -! Default :: 6|7|1 -! The tensor integral reduction library.The current choices are: -! 1 | CutTools -! 2 | PJFry++ -! 3 | IREGI -! 4 | Golem95 -! 5 | Samurai -! 6 | Ninja -! 7 | COLLIER -! One can use the combinations to reduce integral,e.g. -! 1|2|3 means first use CutTools, if it is not stable, use PJFry++, -! if it is still unstable, use IREGI. If it failed, use QP of CutTools. -! Notice that any reduction tool not avaialble on the system will be automatically -! skipped. - -! When using quadruple precision with Ninja or CutTools, the reduction will -! always be done in quadruple precision, but the parameters below allow you to -! chose if you want to also recompute the *integrand* in quadruple precision. -! Doing so is slow but might improve the accuracy in some situation. -#UseQPIntegrandForCutTools -!.TRUE. -! Default :: .TRUE. -#UseQPIntegrandForNinja -!.TRUE. -! Default :: .TRUE. -! - -! ================================================================================= -! The parameters below set the parameters for IREGI -! ================================================================================= - -#IREGIMODE -!2 -! Default :: 2 -! IREGIMODE=0, IBP reduction -! IREGIMODE=1, PaVe reduction -! IREGIMODE=2, PaVe reduction with stablility improved by IBP reduction - -#IREGIRECY -!.TRUE. -! Default :: .TRUE. -! Use RECYCLING OR NOT IN IREGI -! - -! ================================================================================= -! The parameters below set the stability checks of MadLoop at run time -! ================================================================================= - -! Decide in which mode to run MadLoop -! -! imode:| description -! 1 | Double precision, loops reduced with propagator in original order -! 2 | Double precision, loops reduced with propagator with reversed order -! 4 | Quadruple precision, loops reduced with propagator in original order -! 5 | Quadruple precision, loops reduced with propagator with reversed order -! -1 | Exhaustive automated numerical stability checks. See below for details. -! -! Due to the architecture of the program, you are better off -! rerunning the full PS point in quadruple precision than just a single loop -! because the two things would almost take the same time. So '-1' is always -! very recommended. -#CTModeRun -!-1 -! Default :: -1 -! In the negative mode -1, MadLoop first evaluates each PS points in modes 1 and 2, -! yielding results Res1 and Res2, and then check if: -! (Res1-Res2)/(2*(Res1+Res2)< MLStabThres -! If it is not the case, MadLoop evaluates again the PS point in modes 4 and 5, -! yielding results Res4 and Res5, and then check if: -! (Res4-Res5)/(2*(Res4+Res5)< MLStabThres -! If it is the case then the unstable phase-space point could be cured. If it is -! not the case, MadLoop outputs a warning. -! Notice that MLStabThres is used only when CTModeRun is negative. -#MLStabThres -!1.0d-3 -! Default :: 1.0d-3 -! You can add other evaluation method to check for the stability in DP and QP. -! Below you can chose if you want to use zero, one or two rotations of the PS point -! in QP. -#NRotations_DP -!0 -! Default :: 0 -#NRotations_QP -!0 -! Default :: 0 - -! By default, MadLoop is allowed to slightly deform the Phase-Space point in input -! so to insure perfect onshellness of the external particles and perfect energy-momentum -! conservation. The deformation is minimal and such that it leaves the input PS point -! unchanged if it already satisfies the physical condiditions mentioned above. -! This integer values select what is the method to be employed preferably to restore this -! precision. It can take the following values: -! -! -1 :: No method is used for double precision computations, and method 2 will be used -! preferentially when quadruple precision (for which this precision improvement -! is mandatory, otherwise quadruple precision is pointless) -! 1 :: This methods imitates what is done in PSMC, namely -! a) Set the space-like momentum of the last external particle to be the -! opposite of the sum of the others (with a minus sign for the initial states). -! b) Rescale all final state space-like momenta by a fixed value x computed such -! that energy is conserved when particles are put exactly onshell. This value -! is determined numericaly via Ralph-Newton's method. -! c) Set all energies to have particles exactly onshell. -! 2 :: This method applies a shift to the energy and the x and y components of the first -! initial state momentum in order to restore exact energy momentum conservation after -! particles have been put exactly onshell via a shift of the z component of their -! momenta. -#ImprovePSPoint -!2 -! Default :: 2 - -! ================================================================================= -! The parameters below set two CutTools internal parameters accessible to the user. -! ================================================================================= - -! Choose here what library to chose for CutTools/TIR to compute the scalar loops of the -! master integral basis. The choices are as follows: -! (Does not apply for Golem95, where OneLOop is always used) -! 2 | OneLOop -! 3 | QCDLoop -#CTLoopLibrary -!2 -! Default :: 2 - -! Choose here the stability threshold used within CutTools to decide when to go to -! higher precision. -#CTStabThres -!1.0d-2 -! Default :: 1.0d-2 - -! ================================================================================= -! The parameters below set the general behavior of MadLoop for the initialization -! ================================================================================= - -! Decide in which mode to run when performing MadLoop's initialization of -! the helicity (and possibly loop) filter. The possible modes are: -! -! Decide in which mode to run MadLoop -! -! imode:| description -! 1 | Double precision, loops reduced with propagator in original order -! 2 | Double precision, loops reduced with propagator with reversed order -! 4 | Quadruple precision, loops reduced with propagator in original order -! 5 | Quadruple precision, loops reduced with propagator with reversed order -! -#CTModeInit -!1 -! Default :: 1 - -! CheckCycle sets on how many PS points trials the initialization filters must be -! obtained. As long as MadLoop does not find that many consecutive PS points for -! which the filters are the same, it will start over but only a maximum of -! MaxAttempts times. -#CheckCycle -!3 -! Default :: 3 -#MaxAttempts -!10 -! Default :: 10 - -! Setting the threshold for deciding wether a numerical contribution is analytically -! zero or not. -#ZeroThres -!1.0d-9 -! Default :: 1.0d-9 - -! Setting the on-shell threshold for deciding whether the invariant variables -! of external momenta are on-shell or not. It will only be used in constructing -! s-matrix in Golem95. -#OSThres -!1.0d-8 -! Default :: 1.0d-8 - -! The setting below is recommended to be on as it allows to systematically used the -! first PS point thrown at ML5 to be used for making sure that the helicity filter -! read from HelFilter.dat is consistent as it might be no longer up to date with -! certain changes of the paramaters by the user. -#DoubleCheckHelicityFilter -!.TRUE. -! Default :: .TRUE. - -! This decides whether to write out the helicity and loop filters to the files -! HelFilters.dat and LoopFilters.dat to save them for future runs. It usually -! preferable but sometimes not desired because of the need of threadlocks in the -! context of mpi parallelization. So it can be turned off here in such cases. -#WriteOutFilters -!.TRUE. -! Default :: .TRUE. - -! Some loop contributions may be zero for some helicities which are however -! contributing. In order to save their computing time, you can chose here to try -! to filter them out. The gain is typically minimal, so it is turned off by default. -#UseLoopFilter -!.FALSE. -! Default :: .FALSE. - -! The integer below set at which level the user wants to filter helicity configuration. -! Notice that this does not entail any approximation. It only offers the possibility of -! performing exact simplifications based on numerical checks. HelicityFilterLevel = -! 0 : No filtering at all. Not HelFilter.dat file will be written out and *all* helicity -! configurations will be computed. -! 1 : Analytically zero helicity configurations will be recognized as such by numerical -! comparisons (using the 'ZeroThres' param) and consistently skipped in further -! computations. -! 2 : Filters both helicity configuration which are analytically zero *and* those -! consistently identical (typically because of CP symmetry). -! (Will only effectively do it if process was generated in 'optimized_mode') -#HelicityFilterLevel -!2 -! Default :: 2 - -! This decides whether consecutive consistency for the loop filtering setup is also -! required. -#LoopInitStartOver -!.FALSE. -! Default :: .FALSE. - -! This decides wether consecutive consistency for the helicity filtering setup is also -! required. Better to set it to false as it can cause problems for unstable processes. -#HelInitStartOver -!.FALSE. -! Default :: .FALSE. - -! ================================================================================= -! The parameters below set the main parameters for COLLIER -! To edit more specific technical COLLIER parameters, modify directly the content -! of the subroutine 'INITCOLLIER' in the file 'MadLoopCommons.f' -! ================================================================================= - -! Decide if COLLIER must be computed multiple times to evaluate the UV pole residues -! (Withing a Monte-Carlo performed in MG5aMC, this is automatically disabled internally) -#COLLIERComputeUVpoles -!.TRUE. -! Default :: .TRUE. - -! Decide if COLLIER must be computed multiple times to evaluate the IR pole residues -! (Withing a Monte-Carlo performed in MG5aMC, this is automatically disabled internally) -#COLLIERComputeIRpoles -!.TRUE. -! Default :: .TRUE. - -! Decide if COLLIER must be computed multiple times to evaluate the IR pole residues -#COLLIERRequiredAccuracy -!1.0d-8 -! Default :: 1.0d-8 -! A value of -1.0d0 means that it will be automatically set from MLStabThres. -! The default value of 1.0d-8 corresponds to the value for which COLLIER's authors -! have optimized the library. - -! Decide whether to use COLLIER's internal stability test or the loop-direction -! switch test instead. -#COLLIERUseInternalStabilityTest -!.TRUE. -! Default :: .TRUE. -! COLLIER's internal stability test is at no extra cost but not as reliable -! as the loop-direction switch test, which however doubles the reduction time. -! This parameter is only relevant when running MadLoop with CTModeRun=-1. -! If you find a large number of unstable points with COLLIER for complicated -! processes, set this parameter to .FALSE. to make sure the PS points flagged -! as unstable with COLLIER really are so. - -! Set up to which N-loop to use the COLLIER global caching system. -#COLLIERGlobalCache -!-1 -! Default :: -1 -! -1 : Enable the global cache for all loops -! 0 : Disable the global cache alltogether -! N : Enable the global cache but only for up to N-loops - -! Use the global cache when evaluating the poles as well (more memory consuming) -! During a Monte-Carlo it is typically not useful anyway, because the pole -! computation is automatically disabled for COLLIER, irrespectively of the value -! of the parameters COLLIERComputepoles specified above. -#COLLIERUseCacheForPoles -!.FALSE. -! Default :: .FALSE. - -! Choose which branch(es) of COLLIER have to be used -#COLLIERMode -!1 -! Default :: 1 -! COLLIERMode=1 : COLI branch -! COLLIERMode=2 : DD branch -! COLLIERMode=3 : Both DD and COLI branch compared - -! Decide if COLLIER can output its information in a log directory. -#COLLIERCanOutput -!.FALSE. -! Default :: .FALSE. - -/* End of param file */ diff --git a/UNITTEST_proc/Cards/MadLoopParams_default.dat b/UNITTEST_proc/Cards/MadLoopParams_default.dat deleted file mode 100644 index 425d909582..0000000000 --- a/UNITTEST_proc/Cards/MadLoopParams_default.dat +++ /dev/null @@ -1,298 +0,0 @@ -! This file is for the user to set the different parameters of MadLoop. -! The name of the variable to define must start with the '#' sign and then -! the value should be put immediately on the next line. - -! -#MLReductionLib -!6|7|1 -! Default :: 6|7|1 -! The tensor integral reduction library.The current choices are: -! 1 | CutTools -! 2 | PJFry++ -! 3 | IREGI -! 4 | Golem95 -! 5 | Samurai -! 6 | Ninja -! 7 | COLLIER -! One can use the combinations to reduce integral,e.g. -! 1|2|3 means first use CutTools, if it is not stable, use PJFry++, -! if it is still unstable, use IREGI. If it failed, use QP of CutTools. -! Notice that any reduction tool not avaialble on the system will be automatically -! skipped. - -! When using quadruple precision with Ninja or CutTools, the reduction will -! always be done in quadruple precision, but the parameters below allow you to -! chose if you want to also recompute the *integrand* in quadruple precision. -! Doing so is slow but might improve the accuracy in some situation. -#UseQPIntegrandForCutTools -!.TRUE. -! Default :: .TRUE. -#UseQPIntegrandForNinja -!.TRUE. -! Default :: .TRUE. -! - -! ================================================================================= -! The parameters below set the parameters for IREGI -! ================================================================================= - -#IREGIMODE -!2 -! Default :: 2 -! IREGIMODE=0, IBP reduction -! IREGIMODE=1, PaVe reduction -! IREGIMODE=2, PaVe reduction with stablility improved by IBP reduction - -#IREGIRECY -!.TRUE. -! Default :: .TRUE. -! Use RECYCLING OR NOT IN IREGI -! - -! ================================================================================= -! The parameters below set the stability checks of MadLoop at run time -! ================================================================================= - -! Decide in which mode to run MadLoop -! -! imode:| description -! 1 | Double precision, loops reduced with propagator in original order -! 2 | Double precision, loops reduced with propagator with reversed order -! 4 | Quadruple precision, loops reduced with propagator in original order -! 5 | Quadruple precision, loops reduced with propagator with reversed order -! -1 | Exhaustive automated numerical stability checks. See below for details. -! -! Due to the architecture of the program, you are better off -! rerunning the full PS point in quadruple precision than just a single loop -! because the two things would almost take the same time. So '-1' is always -! very recommended. -#CTModeRun -!-1 -! Default :: -1 -! In the negative mode -1, MadLoop first evaluates each PS points in modes 1 and 2, -! yielding results Res1 and Res2, and then check if: -! (Res1-Res2)/(2*(Res1+Res2)< MLStabThres -! If it is not the case, MadLoop evaluates again the PS point in modes 4 and 5, -! yielding results Res4 and Res5, and then check if: -! (Res4-Res5)/(2*(Res4+Res5)< MLStabThres -! If it is the case then the unstable phase-space point could be cured. If it is -! not the case, MadLoop outputs a warning. -! Notice that MLStabThres is used only when CTModeRun is negative. -#MLStabThres -!1.0d-3 -! Default :: 1.0d-3 -! You can add other evaluation method to check for the stability in DP and QP. -! Below you can chose if you want to use zero, one or two rotations of the PS point -! in QP. -#NRotations_DP -!0 -! Default :: 0 -#NRotations_QP -!0 -! Default :: 0 - -! By default, MadLoop is allowed to slightly deform the Phase-Space point in input -! so to insure perfect onshellness of the external particles and perfect energy-momentum -! conservation. The deformation is minimal and such that it leaves the input PS point -! unchanged if it already satisfies the physical condiditions mentioned above. -! This integer values select what is the method to be employed preferably to restore this -! precision. It can take the following values: -! -! -1 :: No method is used for double precision computations, and method 2 will be used -! preferentially when quadruple precision (for which this precision improvement -! is mandatory, otherwise quadruple precision is pointless) -! 1 :: This methods imitates what is done in PSMC, namely -! a) Set the space-like momentum of the last external particle to be the -! opposite of the sum of the others (with a minus sign for the initial states). -! b) Rescale all final state space-like momenta by a fixed value x computed such -! that energy is conserved when particles are put exactly onshell. This value -! is determined numericaly via Ralph-Newton's method. -! c) Set all energies to have particles exactly onshell. -! 2 :: This method applies a shift to the energy and the x and y components of the first -! initial state momentum in order to restore exact energy momentum conservation after -! particles have been put exactly onshell via a shift of the z component of their -! momenta. -#ImprovePSPoint -!2 -! Default :: 2 - -! ================================================================================= -! The parameters below set two CutTools internal parameters accessible to the user. -! ================================================================================= - -! Choose here what library to chose for CutTools/TIR to compute the scalar loops of the -! master integral basis. The choices are as follows: -! (Does not apply for Golem95, where OneLOop is always used) -! 2 | OneLOop -! 3 | QCDLoop -#CTLoopLibrary -!2 -! Default :: 2 - -! Choose here the stability threshold used within CutTools to decide when to go to -! higher precision. -#CTStabThres -!1.0d-2 -! Default :: 1.0d-2 - -! ================================================================================= -! The parameters below set the general behavior of MadLoop for the initialization -! ================================================================================= - -! Decide in which mode to run when performing MadLoop's initialization of -! the helicity (and possibly loop) filter. The possible modes are: -! -! Decide in which mode to run MadLoop -! -! imode:| description -! 1 | Double precision, loops reduced with propagator in original order -! 2 | Double precision, loops reduced with propagator with reversed order -! 4 | Quadruple precision, loops reduced with propagator in original order -! 5 | Quadruple precision, loops reduced with propagator with reversed order -! -#CTModeInit -!1 -! Default :: 1 - -! CheckCycle sets on how many PS points trials the initialization filters must be -! obtained. As long as MadLoop does not find that many consecutive PS points for -! which the filters are the same, it will start over but only a maximum of -! MaxAttempts times. -#CheckCycle -!3 -! Default :: 3 -#MaxAttempts -!10 -! Default :: 10 - -! Setting the threshold for deciding wether a numerical contribution is analytically -! zero or not. -#ZeroThres -!1.0d-9 -! Default :: 1.0d-9 - -! Setting the on-shell threshold for deciding whether the invariant variables -! of external momenta are on-shell or not. It will only be used in constructing -! s-matrix in Golem95. -#OSThres -!1.0d-8 -! Default :: 1.0d-8 - -! The setting below is recommended to be on as it allows to systematically used the -! first PS point thrown at ML5 to be used for making sure that the helicity filter -! read from HelFilter.dat is consistent as it might be no longer up to date with -! certain changes of the paramaters by the user. -#DoubleCheckHelicityFilter -!.TRUE. -! Default :: .TRUE. - -! This decides whether to write out the helicity and loop filters to the files -! HelFilters.dat and LoopFilters.dat to save them for future runs. It usually -! preferable but sometimes not desired because of the need of threadlocks in the -! context of mpi parallelization. So it can be turned off here in such cases. -#WriteOutFilters -!.TRUE. -! Default :: .TRUE. - -! Some loop contributions may be zero for some helicities which are however -! contributing. In order to save their computing time, you can chose here to try -! to filter them out. The gain is typically minimal, so it is turned off by default. -#UseLoopFilter -!.FALSE. -! Default :: .FALSE. - -! The integer below set at which level the user wants to filter helicity configuration. -! Notice that this does not entail any approximation. It only offers the possibility of -! performing exact simplifications based on numerical checks. HelicityFilterLevel = -! 0 : No filtering at all. Not HelFilter.dat file will be written out and *all* helicity -! configurations will be computed. -! 1 : Analytically zero helicity configurations will be recognized as such by numerical -! comparisons (using the 'ZeroThres' param) and consistently skipped in further -! computations. -! 2 : Filters both helicity configuration which are analytically zero *and* those -! consistently identical (typically because of CP symmetry). -! (Will only effectively do it if process was generated in 'optimized_mode') -#HelicityFilterLevel -!2 -! Default :: 2 - -! This decides whether consecutive consistency for the loop filtering setup is also -! required. -#LoopInitStartOver -!.FALSE. -! Default :: .FALSE. - -! This decides wether consecutive consistency for the helicity filtering setup is also -! required. Better to set it to false as it can cause problems for unstable processes. -#HelInitStartOver -!.FALSE. -! Default :: .FALSE. - -! ================================================================================= -! The parameters below set the main parameters for COLLIER -! To edit more specific technical COLLIER parameters, modify directly the content -! of the subroutine 'INITCOLLIER' in the file 'MadLoopCommons.f' -! ================================================================================= - -! Decide if COLLIER must be computed multiple times to evaluate the UV pole residues -! (Withing a Monte-Carlo performed in MG5aMC, this is automatically disabled internally) -#COLLIERComputeUVpoles -!.TRUE. -! Default :: .TRUE. - -! Decide if COLLIER must be computed multiple times to evaluate the IR pole residues -! (Withing a Monte-Carlo performed in MG5aMC, this is automatically disabled internally) -#COLLIERComputeIRpoles -!.TRUE. -! Default :: .TRUE. - -! Decide if COLLIER must be computed multiple times to evaluate the IR pole residues -#COLLIERRequiredAccuracy -!1.0d-8 -! Default :: 1.0d-8 -! A value of -1.0d0 means that it will be automatically set from MLStabThres. -! The default value of 1.0d-8 corresponds to the value for which COLLIER's authors -! have optimized the library. - -! Decide whether to use COLLIER's internal stability test or the loop-direction -! switch test instead. -#COLLIERUseInternalStabilityTest -!.TRUE. -! Default :: .TRUE. -! COLLIER's internal stability test is at no extra cost but not as reliable -! as the loop-direction switch test, which however doubles the reduction time. -! This parameter is only relevant when running MadLoop with CTModeRun=-1. -! If you find a large number of unstable points with COLLIER for complicated -! processes, set this parameter to .FALSE. to make sure the PS points flagged -! as unstable with COLLIER really are so. - -! Set up to which N-loop to use the COLLIER global caching system. -#COLLIERGlobalCache -!-1 -! Default :: -1 -! -1 : Enable the global cache for all loops -! 0 : Disable the global cache alltogether -! N : Enable the global cache but only for up to N-loops - -! Use the global cache when evaluating the poles as well (more memory consuming) -! During a Monte-Carlo it is typically not useful anyway, because the pole -! computation is automatically disabled for COLLIER, irrespectively of the value -! of the parameters COLLIERComputepoles specified above. -#COLLIERUseCacheForPoles -!.FALSE. -! Default :: .FALSE. - -! Choose which branch(es) of COLLIER have to be used -#COLLIERMode -!1 -! Default :: 1 -! COLLIERMode=1 : COLI branch -! COLLIERMode=2 : DD branch -! COLLIERMode=3 : Both DD and COLI branch compared - -! Decide if COLLIER can output its information in a log directory. -#COLLIERCanOutput -!.FALSE. -! Default :: .FALSE. - -/* End of param file */ diff --git a/UNITTEST_proc/Cards/ident_card.dat b/UNITTEST_proc/Cards/ident_card.dat deleted file mode 100644 index debdfc8611..0000000000 --- a/UNITTEST_proc/Cards/ident_card.dat +++ /dev/null @@ -1,35 +0,0 @@ -ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c written by the UFO converter -ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc - -loop 1 MU_R - -sminputs 1 aEWM1 - -sminputs 2 mdl_Gf - -sminputs 3 aS - -yukawa 5 mdl_ymb - -yukawa 6 mdl_ymt - -yukawa 15 mdl_ymtau - -mass 6 mdl_MT - -mass 5 mdl_MB - -mass 23 mdl_MZ - -mass 25 mdl_MH - -mass 15 mdl_MTA - -decay 6 mdl_WT - -decay 23 mdl_WZ - -decay 24 mdl_WW - -decay 25 mdl_WH diff --git a/UNITTEST_proc/Cards/param_card.dat b/UNITTEST_proc/Cards/param_card.dat deleted file mode 100644 index faa7fa5274..0000000000 --- a/UNITTEST_proc/Cards/param_card.dat +++ /dev/null @@ -1,93 +0,0 @@ -###################################################################### -## PARAM_CARD AUTOMATICALLY GENERATED BY MG5 FOLLOWING UFO MODEL #### -###################################################################### -## ## -## Width set on Auto will be computed following the information ## -## present in the decay.py files of the model. ## -## See arXiv:1402.1178 for more details. ## -## ## -###################################################################### - -################################### -## INFORMATION FOR LOOP -################################### -Block loop - 1 9.118800e+01 # MU_R - -################################### -## INFORMATION FOR MASS -################################### -Block mass - 5 4.700000e+00 # MB - 6 1.730000e+02 # MT - 15 1.777000e+00 # MTA - 23 9.118800e+01 # MZ - 25 1.250000e+02 # MH -## Dependent parameters, given by model restrictions. -## Those values should be edited following the -## analytical expression. MG5 ignores those values -## but they are important for interfacing the output of MG5 -## to external program such as Pythia. - 1 0.000000e+00 # d : 0.0 - 2 0.000000e+00 # u : 0.0 - 3 0.000000e+00 # s : 0.0 - 4 0.000000e+00 # c : 0.0 - 11 0.000000e+00 # e- : 0.0 - 12 0.000000e+00 # ve : 0.0 - 13 0.000000e+00 # m- : 0.0 - 14 0.000000e+00 # vm : 0.0 - 16 0.000000e+00 # vt : 0.0 - 21 0.000000e+00 # g : 0.0 - 22 0.000000e+00 # a : 0.0 - 24 8.041900e+01 # w+ : cmath.sqrt(MZ__exp__2/2. + cmath.sqrt(MZ__exp__4/4. - (aEW*cmath.pi*MZ__exp__2)/(Gf*sqrt__2))) - -################################### -## INFORMATION FOR SMINPUTS -################################### -Block sminputs - 1 1.325070e+02 # aEWM1 - 2 1.166390e-05 # Gf - 3 1.180000e-01 # aS (Note: this Parameter is not used if you use a PDF set) - -################################### -## INFORMATION FOR YUKAWA -################################### -Block yukawa - 5 4.700000e+00 # ymb - 6 1.730000e+02 # ymt - 15 1.777000e+00 # ymtau - -################################### -## INFORMATION FOR DECAY -################################### -DECAY 6 1.491500e+00 # WT -DECAY 23 2.441404e+00 # WZ -DECAY 24 2.047600e+00 # WW -DECAY 25 6.382339e-03 # WH -## Dependent parameters, given by model restrictions. -## Those values should be edited following the -## analytical expression. MG5 ignores those values -## but they are important for interfacing the output of MG5 -## to external program such as Pythia. -DECAY 1 0.000000e+00 # d : 0.0 -DECAY 2 0.000000e+00 # u : 0.0 -DECAY 3 0.000000e+00 # s : 0.0 -DECAY 4 0.000000e+00 # c : 0.0 -DECAY 5 0.000000e+00 # b : 0.0 -DECAY 11 0.000000e+00 # e- : 0.0 -DECAY 12 0.000000e+00 # ve : 0.0 -DECAY 13 0.000000e+00 # m- : 0.0 -DECAY 14 0.000000e+00 # vm : 0.0 -DECAY 15 0.000000e+00 # tt- : 0.0 -DECAY 16 0.000000e+00 # vt : 0.0 -DECAY 21 0.000000e+00 # g : 0.0 -DECAY 22 0.000000e+00 # a : 0.0 -#=========================================================== -# QUANTUM NUMBERS OF NEW STATE(S) (NON SM PDG CODE) -#=========================================================== - -Block QNUMBERS 82 # gh - 1 0 # 3 times electric charge - 2 1 # number of spin states (2S+1) - 3 8 # colour rep (1: singlet, 3: triplet, 8: octet) - 4 1 # Particle/Antiparticle distinction (0=own anti) diff --git a/UNITTEST_proc/Cards/param_card_default.dat b/UNITTEST_proc/Cards/param_card_default.dat deleted file mode 100644 index faa7fa5274..0000000000 --- a/UNITTEST_proc/Cards/param_card_default.dat +++ /dev/null @@ -1,93 +0,0 @@ -###################################################################### -## PARAM_CARD AUTOMATICALLY GENERATED BY MG5 FOLLOWING UFO MODEL #### -###################################################################### -## ## -## Width set on Auto will be computed following the information ## -## present in the decay.py files of the model. ## -## See arXiv:1402.1178 for more details. ## -## ## -###################################################################### - -################################### -## INFORMATION FOR LOOP -################################### -Block loop - 1 9.118800e+01 # MU_R - -################################### -## INFORMATION FOR MASS -################################### -Block mass - 5 4.700000e+00 # MB - 6 1.730000e+02 # MT - 15 1.777000e+00 # MTA - 23 9.118800e+01 # MZ - 25 1.250000e+02 # MH -## Dependent parameters, given by model restrictions. -## Those values should be edited following the -## analytical expression. MG5 ignores those values -## but they are important for interfacing the output of MG5 -## to external program such as Pythia. - 1 0.000000e+00 # d : 0.0 - 2 0.000000e+00 # u : 0.0 - 3 0.000000e+00 # s : 0.0 - 4 0.000000e+00 # c : 0.0 - 11 0.000000e+00 # e- : 0.0 - 12 0.000000e+00 # ve : 0.0 - 13 0.000000e+00 # m- : 0.0 - 14 0.000000e+00 # vm : 0.0 - 16 0.000000e+00 # vt : 0.0 - 21 0.000000e+00 # g : 0.0 - 22 0.000000e+00 # a : 0.0 - 24 8.041900e+01 # w+ : cmath.sqrt(MZ__exp__2/2. + cmath.sqrt(MZ__exp__4/4. - (aEW*cmath.pi*MZ__exp__2)/(Gf*sqrt__2))) - -################################### -## INFORMATION FOR SMINPUTS -################################### -Block sminputs - 1 1.325070e+02 # aEWM1 - 2 1.166390e-05 # Gf - 3 1.180000e-01 # aS (Note: this Parameter is not used if you use a PDF set) - -################################### -## INFORMATION FOR YUKAWA -################################### -Block yukawa - 5 4.700000e+00 # ymb - 6 1.730000e+02 # ymt - 15 1.777000e+00 # ymtau - -################################### -## INFORMATION FOR DECAY -################################### -DECAY 6 1.491500e+00 # WT -DECAY 23 2.441404e+00 # WZ -DECAY 24 2.047600e+00 # WW -DECAY 25 6.382339e-03 # WH -## Dependent parameters, given by model restrictions. -## Those values should be edited following the -## analytical expression. MG5 ignores those values -## but they are important for interfacing the output of MG5 -## to external program such as Pythia. -DECAY 1 0.000000e+00 # d : 0.0 -DECAY 2 0.000000e+00 # u : 0.0 -DECAY 3 0.000000e+00 # s : 0.0 -DECAY 4 0.000000e+00 # c : 0.0 -DECAY 5 0.000000e+00 # b : 0.0 -DECAY 11 0.000000e+00 # e- : 0.0 -DECAY 12 0.000000e+00 # ve : 0.0 -DECAY 13 0.000000e+00 # m- : 0.0 -DECAY 14 0.000000e+00 # vm : 0.0 -DECAY 15 0.000000e+00 # tt- : 0.0 -DECAY 16 0.000000e+00 # vt : 0.0 -DECAY 21 0.000000e+00 # g : 0.0 -DECAY 22 0.000000e+00 # a : 0.0 -#=========================================================== -# QUANTUM NUMBERS OF NEW STATE(S) (NON SM PDG CODE) -#=========================================================== - -Block QNUMBERS 82 # gh - 1 0 # 3 times electric charge - 2 1 # number of spin states (2S+1) - 3 8 # colour rep (1: singlet, 3: triplet, 8: octet) - 4 1 # Particle/Antiparticle distinction (0=own anti) diff --git a/UNITTEST_proc/MGMEVersion.txt b/UNITTEST_proc/MGMEVersion.txt deleted file mode 100644 index 0281a4e427..0000000000 --- a/UNITTEST_proc/MGMEVersion.txt +++ /dev/null @@ -1 +0,0 @@ -5.3.7.2 \ No newline at end of file diff --git a/UNITTEST_proc/Source/DHELAS/FFV1LP0_3.f b/UNITTEST_proc/Source/DHELAS/FFV1LP0_3.f deleted file mode 100644 index a03d6ab4a1..0000000000 --- a/UNITTEST_proc/Source/DHELAS/FFV1LP0_3.f +++ /dev/null @@ -1,29 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C Gamma(3,2,1) -C - SUBROUTINE FFV1LP0_3(F1, F2, COUP, M3, W3,V3) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*16 CI - PARAMETER (CI=(0D0,1D0)) - COMPLEX*16 COUP - TYPE(ALOHA) F1 - INTEGER FLV_INDEX1 - TYPE(ALOHA) F2 - INTEGER FLV_INDEX2 - REAL*8 M3 - TYPE(ALOHA) V3 - REAL*8 W3 - V3%P(:) = +F1%P(:)+F2%P(:) - V3%W(1)= COUP*(-CI)*(F2 % W(3)*F1 % W(1)+F2 % W(4)*F1 % W(2)+F2 - $ % W(1)*F1 % W(3)+F2 % W(2)*F1 % W(4)) - V3%W(2)= COUP*(-CI)*(-F2 % W(4)*F1 % W(1)-F2 % W(3)*F1 % W(2)+F2 - $ % W(2)*F1 % W(3)+F2 % W(1)*F1 % W(4)) - V3%W(3)= COUP*(-CI)*(-CI*(F2 % W(4)*F1 % W(1)+F2 % W(1)*F1 % W(4) - $ )+CI*(F2 % W(3)*F1 % W(2)+F2 % W(2)*F1 % W(3))) - V3%W(4)= COUP*(-CI)*(-F2 % W(3)*F1 % W(1)-F2 % W(2)*F1 % W(4)+F2 - $ % W(4)*F1 % W(2)+F2 % W(1)*F1 % W(3)) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/FFV1L_1.f b/UNITTEST_proc/Source/DHELAS/FFV1L_1.f deleted file mode 100644 index 6a648b7657..0000000000 --- a/UNITTEST_proc/Source/DHELAS/FFV1L_1.f +++ /dev/null @@ -1,51 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C Gamma(3,2,1) -C - SUBROUTINE FFV1L_1(F2, V3, COUP, M1, W1,F1) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*16 CI - PARAMETER (CI=(0D0,1D0)) - COMPLEX*16 COUP - TYPE(ALOHA) F1 - INTEGER FLV_INDEX1 - TYPE(ALOHA) F2 - INTEGER FLV_INDEX2 - REAL*8 M1 - COMPLEX*16 P1(0:3) - TYPE(ALOHA) V3 - REAL*8 W1 - F1%P(:) = +F2%P(:)+V3%P(:) - P1(:) = -F1 % P (:) - F1%W(1)= COUP*CI*(F2 % W(1)*(P1(0)*(-V3 % W(1)+V3 % W(4))+(P1(1) - $ *(V3 % W(2)-CI*(V3 % W(3)))+(P1(2)*(+CI*(V3 % W(2))+V3 % W(3)) - $ +P1(3)*(-V3 % W(1)+V3 % W(4)))))+(F2 % W(2)*(P1(0)*(V3 % W(2) - $ +CI*(V3 % W(3)))+(P1(1)*(-1D0)*(V3 % W(1)+V3 % W(4))+(P1(2)*( - $ -1D0)*(+CI*(V3 % W(1)+V3 % W(4)))+P1(3)*(V3 % W(2)+CI*(V3 % W(3) - $ )))))+M1*(F2 % W(3)*(V3 % W(1)+V3 % W(4))+F2 % W(4)*(V3 % W(2) - $ +CI*(V3 % W(3)))))) - F1%W(2)= COUP*(-CI)*(F2 % W(1)*(P1(0)*(-V3 % W(2)+CI*(V3 % W(3))) - $ +(P1(1)*(V3 % W(1)-V3 % W(4))+(P1(2)*(-CI*(V3 % W(1))+CI*(V3 % - $ W(4)))+P1(3)*(V3 % W(2)-CI*(V3 % W(3))))))+(F2 % W(2)*(P1(0) - $ *(V3 % W(1)+V3 % W(4))+(P1(1)*(-1D0)*(V3 % W(2)+CI*(V3 % W(3))) - $ +(P1(2)*(+CI*(V3 % W(2))-V3 % W(3))-P1(3)*(V3 % W(1)+V3 % W(4))) - $ ))+M1*(F2 % W(3)*(-V3 % W(2)+CI*(V3 % W(3)))+F2 % W(4)*(-V3 % - $ W(1)+V3 % W(4))))) - F1%W(3)= COUP*(-CI)*(F2 % W(3)*(P1(0)*(V3 % W(1)+V3 % W(4)) - $ +(P1(1)*(-V3 % W(2)+CI*(V3 % W(3)))+(P1(2)*(-1D0)*(+CI*(V3 % - $ W(2))+V3 % W(3))-P1(3)*(V3 % W(1)+V3 % W(4)))))+(F2 % W(4) - $ *(P1(0)*(V3 % W(2)+CI*(V3 % W(3)))+(P1(1)*(-V3 % W(1)+V3 % W(4)) - $ +(P1(2)*(-CI*(V3 % W(1))+CI*(V3 % W(4)))-P1(3)*(V3 % W(2)+CI - $ *(V3 % W(3))))))+M1*(F2 % W(1)*(-V3 % W(1)+V3 % W(4))+F2 % W(2) - $ *(V3 % W(2)+CI*(V3 % W(3)))))) - F1%W(4)= COUP*CI*(F2 % W(3)*(P1(0)*(-V3 % W(2)+CI*(V3 % W(3))) - $ +(P1(1)*(V3 % W(1)+V3 % W(4))+(P1(2)*(-1D0)*(+CI*(V3 % W(1)+V3 - $ % W(4)))+P1(3)*(-V3 % W(2)+CI*(V3 % W(3))))))+(F2 % W(4)*(P1(0) - $ *(-V3 % W(1)+V3 % W(4))+(P1(1)*(V3 % W(2)+CI*(V3 % W(3)))+(P1(2) - $ *(-CI*(V3 % W(2))+V3 % W(3))+P1(3)*(-V3 % W(1)+V3 % W(4)))))+M1 - $ *(F2 % W(1)*(-V3 % W(2)+CI*(V3 % W(3)))+F2 % W(2)*(V3 % W(1)+V3 - $ % W(4))))) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/FFV1L_2.f b/UNITTEST_proc/Source/DHELAS/FFV1L_2.f deleted file mode 100644 index 5df2242794..0000000000 --- a/UNITTEST_proc/Source/DHELAS/FFV1L_2.f +++ /dev/null @@ -1,51 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C Gamma(3,2,1) -C - SUBROUTINE FFV1L_2(F1, V3, COUP, M2, W2,F2) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*16 CI - PARAMETER (CI=(0D0,1D0)) - COMPLEX*16 COUP - TYPE(ALOHA) F1 - INTEGER FLV_INDEX1 - TYPE(ALOHA) F2 - INTEGER FLV_INDEX2 - REAL*8 M2 - COMPLEX*16 P2(0:3) - TYPE(ALOHA) V3 - REAL*8 W2 - F2%P(:) = +F1%P(:)+V3%P(:) - P2(:) = -F2 % P (:) - F2%W(1)= COUP*CI*(F1 % W(1)*(P2(0)*(V3 % W(1)+V3 % W(4))+(P2(1) - $ *(-1D0)*(V3 % W(2)+CI*(V3 % W(3)))+(P2(2)*(+CI*(V3 % W(2))-V3 % - $ W(3))-P2(3)*(V3 % W(1)+V3 % W(4)))))+(F1 % W(2)*(P2(0)*(V3 % - $ W(2)-CI*(V3 % W(3)))+(P2(1)*(-V3 % W(1)+V3 % W(4))+(P2(2)*(+CI - $ *(V3 % W(1))-CI*(V3 % W(4)))+P2(3)*(-V3 % W(2)+CI*(V3 % W(3))))) - $ )+M2*(F1 % W(3)*(V3 % W(1)-V3 % W(4))+F1 % W(4)*(-V3 % W(2)+CI - $ *(V3 % W(3)))))) - F2%W(2)= COUP*(-CI)*(F1 % W(1)*(P2(0)*(-1D0)*(V3 % W(2)+CI*(V3 % - $ W(3)))+(P2(1)*(V3 % W(1)+V3 % W(4))+(P2(2)*(+CI*(V3 % W(1)+V3 - $ % W(4)))-P2(3)*(V3 % W(2)+CI*(V3 % W(3))))))+(F1 % W(2)*(P2(0) - $ *(-V3 % W(1)+V3 % W(4))+(P2(1)*(V3 % W(2)-CI*(V3 % W(3)))+(P2(2) - $ *(+CI*(V3 % W(2))+V3 % W(3))+P2(3)*(-V3 % W(1)+V3 % W(4)))))+M2 - $ *(F1 % W(3)*(V3 % W(2)+CI*(V3 % W(3)))-F1 % W(4)*(V3 % W(1)+V3 - $ % W(4))))) - F2%W(3)= COUP*(-CI)*(F1 % W(3)*(P2(0)*(-V3 % W(1)+V3 % W(4)) - $ +(P2(1)*(V3 % W(2)+CI*(V3 % W(3)))+(P2(2)*(-CI*(V3 % W(2))+V3 % - $ W(3))+P2(3)*(-V3 % W(1)+V3 % W(4)))))+(F1 % W(4)*(P2(0)*(V3 % - $ W(2)-CI*(V3 % W(3)))+(P2(1)*(-1D0)*(V3 % W(1)+V3 % W(4))+(P2(2) - $ *(+CI*(V3 % W(1)+V3 % W(4)))+P2(3)*(V3 % W(2)-CI*(V3 % W(3)))))) - $ +M2*(F1 % W(1)*(-1D0)*(V3 % W(1)+V3 % W(4))+F1 % W(2)*(-V3 % - $ W(2)+CI*(V3 % W(3)))))) - F2%W(4)= COUP*CI*(F1 % W(3)*(P2(0)*(-1D0)*(V3 % W(2)+CI*(V3 % - $ W(3)))+(P2(1)*(V3 % W(1)-V3 % W(4))+(P2(2)*(+CI*(V3 % W(1))-CI - $ *(V3 % W(4)))+P2(3)*(V3 % W(2)+CI*(V3 % W(3))))))+(F1 % W(4) - $ *(P2(0)*(V3 % W(1)+V3 % W(4))+(P2(1)*(-V3 % W(2)+CI*(V3 % W(3))) - $ +(P2(2)*(-1D0)*(+CI*(V3 % W(2))+V3 % W(3))-P2(3)*(V3 % W(1)+V3 - $ % W(4)))))+M2*(F1 % W(1)*(V3 % W(2)+CI*(V3 % W(3)))+F1 % W(2) - $ *(V3 % W(1)-V3 % W(4))))) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/FFV1P0_3.f b/UNITTEST_proc/Source/DHELAS/FFV1P0_3.f deleted file mode 100644 index e537fbd97f..0000000000 --- a/UNITTEST_proc/Source/DHELAS/FFV1P0_3.f +++ /dev/null @@ -1,40 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C Gamma(3,2,1) -C - SUBROUTINE FFV1P0_3(F1, F2, COUP, M3, W3,V3) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*16 CI - PARAMETER (CI=(0D0,1D0)) - COMPLEX*16 COUP - TYPE(ALOHA) F1 - INTEGER FLV_INDEX1 - TYPE(ALOHA) F2 - INTEGER FLV_INDEX2 - REAL*8 M3 - REAL*8 P3(0:3) - TYPE(ALOHA) V3 - REAL*8 W3 - COMPLEX*16 DENOM - V3%P(:) = +F1%P(:)+F2%P(:) - P3(:) = -V3 % P (:) - FLV_INDEX1 = F1 %FLV_INDEX - FLV_INDEX2 = F2 %FLV_INDEX - IF(FLV_INDEX1.NE.FLV_INDEX2.OR.FLV_INDEX1.EQ.0)THEN - V3%W(:) = (0D0,0D0) - RETURN - ENDIF - DENOM = COUP/(P3(0)**2-P3(1)**2-P3(2)**2-P3(3)**2 - M3 * (M3 -CI - $ * W3)) - V3%W(1)= DENOM*(-CI)*(F2 % W(3)*F1 % W(1)+F2 % W(4)*F1 % W(2)+F2 - $ % W(1)*F1 % W(3)+F2 % W(2)*F1 % W(4)) - V3%W(2)= DENOM*(-CI)*(-F2 % W(4)*F1 % W(1)-F2 % W(3)*F1 % W(2) - $ +F2 % W(2)*F1 % W(3)+F2 % W(1)*F1 % W(4)) - V3%W(3)= DENOM*(-CI)*(-CI*(F2 % W(4)*F1 % W(1)+F2 % W(1)*F1 % - $ W(4))+CI*(F2 % W(3)*F1 % W(2)+F2 % W(2)*F1 % W(3))) - V3%W(4)= DENOM*(-CI)*(-F2 % W(3)*F1 % W(1)-F2 % W(2)*F1 % W(4) - $ +F2 % W(4)*F1 % W(2)+F2 % W(1)*F1 % W(3)) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/FFV1_0.f b/UNITTEST_proc/Source/DHELAS/FFV1_0.f deleted file mode 100644 index a2f6d26199..0000000000 --- a/UNITTEST_proc/Source/DHELAS/FFV1_0.f +++ /dev/null @@ -1,33 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C Gamma(3,2,1) -C - SUBROUTINE FFV1_0(F1, F2, V3, COUP,VERTEX) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*16 CI - PARAMETER (CI=(0D0,1D0)) - COMPLEX*16 COUP - TYPE(ALOHA) F1 - INTEGER FLV_INDEX1 - TYPE(ALOHA) F2 - INTEGER FLV_INDEX2 - COMPLEX*16 TMP10 - TYPE(ALOHA) V3 - COMPLEX*16 VERTEX - FLV_INDEX1 = F1 %FLV_INDEX - FLV_INDEX2 = F2 %FLV_INDEX - IF(FLV_INDEX1.NE.FLV_INDEX2.OR.FLV_INDEX1.EQ.0)THEN - VERTEX = (0D0,0D0) - RETURN - ENDIF - TMP10 = (F1 % W(1)*(F2 % W(3)*(V3 % W(1)+V3 % W(4))+F2 % W(4) - $ *(V3 % W(2)+CI*(V3 % W(3))))+(F1 % W(2)*(F2 % W(3)*(V3 % W(2) - $ -CI*(V3 % W(3)))+F2 % W(4)*(V3 % W(1)-V3 % W(4)))+(F1 % W(3) - $ *(F2 % W(1)*(V3 % W(1)-V3 % W(4))-F2 % W(2)*(V3 % W(2)+CI*(V3 % - $ W(3))))+F1 % W(4)*(F2 % W(1)*(-V3 % W(2)+CI*(V3 % W(3)))+F2 % - $ W(2)*(V3 % W(1)+V3 % W(4)))))) - VERTEX = COUP*(-CI * TMP10) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/FFV1_1.f b/UNITTEST_proc/Source/DHELAS/FFV1_1.f deleted file mode 100644 index d61c39598c..0000000000 --- a/UNITTEST_proc/Source/DHELAS/FFV1_1.f +++ /dev/null @@ -1,55 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C Gamma(3,2,1) -C - SUBROUTINE FFV1_1(F2, V3, COUP, M1, W1,F1) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*16 CI - PARAMETER (CI=(0D0,1D0)) - COMPLEX*16 COUP - TYPE(ALOHA) F1 - INTEGER FLV_INDEX1 - TYPE(ALOHA) F2 - INTEGER FLV_INDEX2 - REAL*8 M1 - REAL*8 P1(0:3) - TYPE(ALOHA) V3 - REAL*8 W1 - COMPLEX*16 DENOM - F1%P(:) = +F2%P(:)+V3%P(:) - P1(:) = -F1 % P (:) - F1 % FLV_INDEX = F2 % FLV_INDEX - DENOM = COUP/(P1(0)**2-P1(1)**2-P1(2)**2-P1(3)**2 - M1 * (M1 -CI - $ * W1)) - F1%W(1)= DENOM*CI*(F2 % W(1)*(P1(0)*(-V3 % W(1)+V3 % W(4))+(P1(1) - $ *(V3 % W(2)-CI*(V3 % W(3)))+(P1(2)*(+CI*(V3 % W(2))+V3 % W(3)) - $ +P1(3)*(-V3 % W(1)+V3 % W(4)))))+(F2 % W(2)*(P1(0)*(V3 % W(2) - $ +CI*(V3 % W(3)))+(P1(1)*(-1D0)*(V3 % W(1)+V3 % W(4))+(P1(2)*( - $ -1D0)*(+CI*(V3 % W(1)+V3 % W(4)))+P1(3)*(V3 % W(2)+CI*(V3 % W(3) - $ )))))+M1*(F2 % W(3)*(V3 % W(1)+V3 % W(4))+F2 % W(4)*(V3 % W(2) - $ +CI*(V3 % W(3)))))) - F1%W(2)= DENOM*(-CI)*(F2 % W(1)*(P1(0)*(-V3 % W(2)+CI*(V3 % W(3)) - $ )+(P1(1)*(V3 % W(1)-V3 % W(4))+(P1(2)*(-CI*(V3 % W(1))+CI*(V3 % - $ W(4)))+P1(3)*(V3 % W(2)-CI*(V3 % W(3))))))+(F2 % W(2)*(P1(0) - $ *(V3 % W(1)+V3 % W(4))+(P1(1)*(-1D0)*(V3 % W(2)+CI*(V3 % W(3))) - $ +(P1(2)*(+CI*(V3 % W(2))-V3 % W(3))-P1(3)*(V3 % W(1)+V3 % W(4))) - $ ))+M1*(F2 % W(3)*(-V3 % W(2)+CI*(V3 % W(3)))+F2 % W(4)*(-V3 % - $ W(1)+V3 % W(4))))) - F1%W(3)= DENOM*(-CI)*(F2 % W(3)*(P1(0)*(V3 % W(1)+V3 % W(4)) - $ +(P1(1)*(-V3 % W(2)+CI*(V3 % W(3)))+(P1(2)*(-1D0)*(+CI*(V3 % - $ W(2))+V3 % W(3))-P1(3)*(V3 % W(1)+V3 % W(4)))))+(F2 % W(4) - $ *(P1(0)*(V3 % W(2)+CI*(V3 % W(3)))+(P1(1)*(-V3 % W(1)+V3 % W(4)) - $ +(P1(2)*(-CI*(V3 % W(1))+CI*(V3 % W(4)))-P1(3)*(V3 % W(2)+CI - $ *(V3 % W(3))))))+M1*(F2 % W(1)*(-V3 % W(1)+V3 % W(4))+F2 % W(2) - $ *(V3 % W(2)+CI*(V3 % W(3)))))) - F1%W(4)= DENOM*CI*(F2 % W(3)*(P1(0)*(-V3 % W(2)+CI*(V3 % W(3))) - $ +(P1(1)*(V3 % W(1)+V3 % W(4))+(P1(2)*(-1D0)*(+CI*(V3 % W(1)+V3 - $ % W(4)))+P1(3)*(-V3 % W(2)+CI*(V3 % W(3))))))+(F2 % W(4)*(P1(0) - $ *(-V3 % W(1)+V3 % W(4))+(P1(1)*(V3 % W(2)+CI*(V3 % W(3)))+(P1(2) - $ *(-CI*(V3 % W(2))+V3 % W(3))+P1(3)*(-V3 % W(1)+V3 % W(4)))))+M1 - $ *(F2 % W(1)*(-V3 % W(2)+CI*(V3 % W(3)))+F2 % W(2)*(V3 % W(1)+V3 - $ % W(4))))) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/FFV1_2.f b/UNITTEST_proc/Source/DHELAS/FFV1_2.f deleted file mode 100644 index 0227b562f7..0000000000 --- a/UNITTEST_proc/Source/DHELAS/FFV1_2.f +++ /dev/null @@ -1,55 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C Gamma(3,2,1) -C - SUBROUTINE FFV1_2(F1, V3, COUP, M2, W2,F2) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*16 CI - PARAMETER (CI=(0D0,1D0)) - COMPLEX*16 COUP - TYPE(ALOHA) F1 - INTEGER FLV_INDEX1 - TYPE(ALOHA) F2 - INTEGER FLV_INDEX2 - REAL*8 M2 - REAL*8 P2(0:3) - TYPE(ALOHA) V3 - REAL*8 W2 - COMPLEX*16 DENOM - F2%P(:) = +F1%P(:)+V3%P(:) - P2(:) = -F2 % P (:) - F2 % FLV_INDEX = F1 % FLV_INDEX - DENOM = COUP/(P2(0)**2-P2(1)**2-P2(2)**2-P2(3)**2 - M2 * (M2 -CI - $ * W2)) - F2%W(1)= DENOM*CI*(F1 % W(1)*(P2(0)*(V3 % W(1)+V3 % W(4))+(P2(1) - $ *(-1D0)*(V3 % W(2)+CI*(V3 % W(3)))+(P2(2)*(+CI*(V3 % W(2))-V3 % - $ W(3))-P2(3)*(V3 % W(1)+V3 % W(4)))))+(F1 % W(2)*(P2(0)*(V3 % - $ W(2)-CI*(V3 % W(3)))+(P2(1)*(-V3 % W(1)+V3 % W(4))+(P2(2)*(+CI - $ *(V3 % W(1))-CI*(V3 % W(4)))+P2(3)*(-V3 % W(2)+CI*(V3 % W(3))))) - $ )+M2*(F1 % W(3)*(V3 % W(1)-V3 % W(4))+F1 % W(4)*(-V3 % W(2)+CI - $ *(V3 % W(3)))))) - F2%W(2)= DENOM*(-CI)*(F1 % W(1)*(P2(0)*(-1D0)*(V3 % W(2)+CI*(V3 - $ % W(3)))+(P2(1)*(V3 % W(1)+V3 % W(4))+(P2(2)*(+CI*(V3 % W(1) - $ +V3 % W(4)))-P2(3)*(V3 % W(2)+CI*(V3 % W(3))))))+(F1 % W(2) - $ *(P2(0)*(-V3 % W(1)+V3 % W(4))+(P2(1)*(V3 % W(2)-CI*(V3 % W(3))) - $ +(P2(2)*(+CI*(V3 % W(2))+V3 % W(3))+P2(3)*(-V3 % W(1)+V3 % W(4)) - $ )))+M2*(F1 % W(3)*(V3 % W(2)+CI*(V3 % W(3)))-F1 % W(4)*(V3 % - $ W(1)+V3 % W(4))))) - F2%W(3)= DENOM*(-CI)*(F1 % W(3)*(P2(0)*(-V3 % W(1)+V3 % W(4)) - $ +(P2(1)*(V3 % W(2)+CI*(V3 % W(3)))+(P2(2)*(-CI*(V3 % W(2))+V3 % - $ W(3))+P2(3)*(-V3 % W(1)+V3 % W(4)))))+(F1 % W(4)*(P2(0)*(V3 % - $ W(2)-CI*(V3 % W(3)))+(P2(1)*(-1D0)*(V3 % W(1)+V3 % W(4))+(P2(2) - $ *(+CI*(V3 % W(1)+V3 % W(4)))+P2(3)*(V3 % W(2)-CI*(V3 % W(3)))))) - $ +M2*(F1 % W(1)*(-1D0)*(V3 % W(1)+V3 % W(4))+F1 % W(2)*(-V3 % - $ W(2)+CI*(V3 % W(3)))))) - F2%W(4)= DENOM*CI*(F1 % W(3)*(P2(0)*(-1D0)*(V3 % W(2)+CI*(V3 % - $ W(3)))+(P2(1)*(V3 % W(1)-V3 % W(4))+(P2(2)*(+CI*(V3 % W(1))-CI - $ *(V3 % W(4)))+P2(3)*(V3 % W(2)+CI*(V3 % W(3))))))+(F1 % W(4) - $ *(P2(0)*(V3 % W(1)+V3 % W(4))+(P2(1)*(-V3 % W(2)+CI*(V3 % W(3))) - $ +(P2(2)*(-1D0)*(+CI*(V3 % W(2))+V3 % W(3))-P2(3)*(V3 % W(1)+V3 - $ % W(4)))))+M2*(F1 % W(1)*(V3 % W(2)+CI*(V3 % W(3)))+F1 % W(2) - $ *(V3 % W(1)-V3 % W(4))))) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/GHGHGL_1.f b/UNITTEST_proc/Source/DHELAS/GHGHGL_1.f deleted file mode 100644 index fec8618ce7..0000000000 --- a/UNITTEST_proc/Source/DHELAS/GHGHGL_1.f +++ /dev/null @@ -1,25 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C P(3,2) -C - SUBROUTINE GHGHGL_1(S2, V3, COUP, M1, W1,S1) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*16 CI - PARAMETER (CI=(0D0,1D0)) - COMPLEX*16 COUP - REAL*8 M1 - COMPLEX*16 P2(0:3) - TYPE(ALOHA) S1 - TYPE(ALOHA) S2 - COMPLEX*16 TMP1 - TYPE(ALOHA) V3 - REAL*8 W1 - P2(:) = S2 % P (:) - S1%P(:) = +S2%P(:)+V3%P(:) - TMP1 = (V3 % W(1)*P2(0)-V3 % W(2)*P2(1)-V3 % W(3)*P2(2)-V3 % W(4) - $ *P2(3)) - S1%W(1)= COUP*CI * TMP1*S2 % W(1) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/GHGHGL_2.f b/UNITTEST_proc/Source/DHELAS/GHGHGL_2.f deleted file mode 100644 index 9c5b0893ae..0000000000 --- a/UNITTEST_proc/Source/DHELAS/GHGHGL_2.f +++ /dev/null @@ -1,25 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C P(3,2) -C - SUBROUTINE GHGHGL_2(S1, V3, COUP, M2, W2,S2) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*16 CI - PARAMETER (CI=(0D0,1D0)) - COMPLEX*16 COUP - REAL*8 M2 - COMPLEX*16 P2(0:3) - TYPE(ALOHA) S1 - TYPE(ALOHA) S2 - COMPLEX*16 TMP1 - TYPE(ALOHA) V3 - REAL*8 W2 - S2%P(:) = +S1%P(:)+V3%P(:) - P2(:) = -S2 % P (:) - TMP1 = (V3 % W(1)*P2(0)-V3 % W(2)*P2(1)-V3 % W(3)*P2(2)-V3 % W(4) - $ *P2(3)) - S2%W(1)= COUP*CI * TMP1*S1 % W(1) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/MP_FFV1LP0_3.f b/UNITTEST_proc/Source/DHELAS/MP_FFV1LP0_3.f deleted file mode 100644 index c35c7b0f80..0000000000 --- a/UNITTEST_proc/Source/DHELAS/MP_FFV1LP0_3.f +++ /dev/null @@ -1,29 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C Gamma(3,2,1) -C - SUBROUTINE MP_FFV1LP0_3(F1, F2, COUP, M3, W3,V3) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*32 CI - PARAMETER (CI=(0Q0,1Q0)) - COMPLEX*32 COUP - TYPE(MP_ALOHA) F1 - INTEGER FLV_INDEX1 - TYPE(MP_ALOHA) F2 - INTEGER FLV_INDEX2 - REAL*16 M3 - TYPE(MP_ALOHA) V3 - REAL*16 W3 - V3%P(:) = +F1%P(:)+F2%P(:) - V3%W(1)= COUP*(-CI)*(F2 % W(3)*F1 % W(1)+F2 % W(4)*F1 % W(2)+F2 - $ % W(1)*F1 % W(3)+F2 % W(2)*F1 % W(4)) - V3%W(2)= COUP*(-CI)*(-F2 % W(4)*F1 % W(1)-F2 % W(3)*F1 % W(2)+F2 - $ % W(2)*F1 % W(3)+F2 % W(1)*F1 % W(4)) - V3%W(3)= COUP*(-CI)*(-CI*(F2 % W(4)*F1 % W(1)+F2 % W(1)*F1 % W(4) - $ )+CI*(F2 % W(3)*F1 % W(2)+F2 % W(2)*F1 % W(3))) - V3%W(4)= COUP*(-CI)*(-F2 % W(3)*F1 % W(1)-F2 % W(2)*F1 % W(4)+F2 - $ % W(4)*F1 % W(2)+F2 % W(1)*F1 % W(3)) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/MP_FFV1L_1.f b/UNITTEST_proc/Source/DHELAS/MP_FFV1L_1.f deleted file mode 100644 index 56ef41d634..0000000000 --- a/UNITTEST_proc/Source/DHELAS/MP_FFV1L_1.f +++ /dev/null @@ -1,51 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C Gamma(3,2,1) -C - SUBROUTINE MP_FFV1L_1(F2, V3, COUP, M1, W1,F1) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*32 CI - PARAMETER (CI=(0Q0,1Q0)) - COMPLEX*32 COUP - TYPE(MP_ALOHA) F1 - INTEGER FLV_INDEX1 - TYPE(MP_ALOHA) F2 - INTEGER FLV_INDEX2 - REAL*16 M1 - COMPLEX*32 P1(0:3) - TYPE(MP_ALOHA) V3 - REAL*16 W1 - F1%P(:) = +F2%P(:)+V3%P(:) - P1(:) = -F1 % P (:) - F1%W(1)= COUP*CI*(F2 % W(1)*(P1(0)*(-V3 % W(1)+V3 % W(4))+(P1(1) - $ *(V3 % W(2)-CI*(V3 % W(3)))+(P1(2)*(+CI*(V3 % W(2))+V3 % W(3)) - $ +P1(3)*(-V3 % W(1)+V3 % W(4)))))+(F2 % W(2)*(P1(0)*(V3 % W(2) - $ +CI*(V3 % W(3)))+(P1(1)*(-1Q0)*(V3 % W(1)+V3 % W(4))+(P1(2)*( - $ -1Q0)*(+CI*(V3 % W(1)+V3 % W(4)))+P1(3)*(V3 % W(2)+CI*(V3 % W(3) - $ )))))+M1*(F2 % W(3)*(V3 % W(1)+V3 % W(4))+F2 % W(4)*(V3 % W(2) - $ +CI*(V3 % W(3)))))) - F1%W(2)= COUP*(-CI)*(F2 % W(1)*(P1(0)*(-V3 % W(2)+CI*(V3 % W(3))) - $ +(P1(1)*(V3 % W(1)-V3 % W(4))+(P1(2)*(-CI*(V3 % W(1))+CI*(V3 % - $ W(4)))+P1(3)*(V3 % W(2)-CI*(V3 % W(3))))))+(F2 % W(2)*(P1(0) - $ *(V3 % W(1)+V3 % W(4))+(P1(1)*(-1Q0)*(V3 % W(2)+CI*(V3 % W(3))) - $ +(P1(2)*(+CI*(V3 % W(2))-V3 % W(3))-P1(3)*(V3 % W(1)+V3 % W(4))) - $ ))+M1*(F2 % W(3)*(-V3 % W(2)+CI*(V3 % W(3)))+F2 % W(4)*(-V3 % - $ W(1)+V3 % W(4))))) - F1%W(3)= COUP*(-CI)*(F2 % W(3)*(P1(0)*(V3 % W(1)+V3 % W(4)) - $ +(P1(1)*(-V3 % W(2)+CI*(V3 % W(3)))+(P1(2)*(-1Q0)*(+CI*(V3 % - $ W(2))+V3 % W(3))-P1(3)*(V3 % W(1)+V3 % W(4)))))+(F2 % W(4) - $ *(P1(0)*(V3 % W(2)+CI*(V3 % W(3)))+(P1(1)*(-V3 % W(1)+V3 % W(4)) - $ +(P1(2)*(-CI*(V3 % W(1))+CI*(V3 % W(4)))-P1(3)*(V3 % W(2)+CI - $ *(V3 % W(3))))))+M1*(F2 % W(1)*(-V3 % W(1)+V3 % W(4))+F2 % W(2) - $ *(V3 % W(2)+CI*(V3 % W(3)))))) - F1%W(4)= COUP*CI*(F2 % W(3)*(P1(0)*(-V3 % W(2)+CI*(V3 % W(3))) - $ +(P1(1)*(V3 % W(1)+V3 % W(4))+(P1(2)*(-1Q0)*(+CI*(V3 % W(1)+V3 - $ % W(4)))+P1(3)*(-V3 % W(2)+CI*(V3 % W(3))))))+(F2 % W(4)*(P1(0) - $ *(-V3 % W(1)+V3 % W(4))+(P1(1)*(V3 % W(2)+CI*(V3 % W(3)))+(P1(2) - $ *(-CI*(V3 % W(2))+V3 % W(3))+P1(3)*(-V3 % W(1)+V3 % W(4)))))+M1 - $ *(F2 % W(1)*(-V3 % W(2)+CI*(V3 % W(3)))+F2 % W(2)*(V3 % W(1)+V3 - $ % W(4))))) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/MP_FFV1L_2.f b/UNITTEST_proc/Source/DHELAS/MP_FFV1L_2.f deleted file mode 100644 index e79f2345a6..0000000000 --- a/UNITTEST_proc/Source/DHELAS/MP_FFV1L_2.f +++ /dev/null @@ -1,51 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C Gamma(3,2,1) -C - SUBROUTINE MP_FFV1L_2(F1, V3, COUP, M2, W2,F2) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*32 CI - PARAMETER (CI=(0Q0,1Q0)) - COMPLEX*32 COUP - TYPE(MP_ALOHA) F1 - INTEGER FLV_INDEX1 - TYPE(MP_ALOHA) F2 - INTEGER FLV_INDEX2 - REAL*16 M2 - COMPLEX*32 P2(0:3) - TYPE(MP_ALOHA) V3 - REAL*16 W2 - F2%P(:) = +F1%P(:)+V3%P(:) - P2(:) = -F2 % P (:) - F2%W(1)= COUP*CI*(F1 % W(1)*(P2(0)*(V3 % W(1)+V3 % W(4))+(P2(1) - $ *(-1Q0)*(V3 % W(2)+CI*(V3 % W(3)))+(P2(2)*(+CI*(V3 % W(2))-V3 % - $ W(3))-P2(3)*(V3 % W(1)+V3 % W(4)))))+(F1 % W(2)*(P2(0)*(V3 % - $ W(2)-CI*(V3 % W(3)))+(P2(1)*(-V3 % W(1)+V3 % W(4))+(P2(2)*(+CI - $ *(V3 % W(1))-CI*(V3 % W(4)))+P2(3)*(-V3 % W(2)+CI*(V3 % W(3))))) - $ )+M2*(F1 % W(3)*(V3 % W(1)-V3 % W(4))+F1 % W(4)*(-V3 % W(2)+CI - $ *(V3 % W(3)))))) - F2%W(2)= COUP*(-CI)*(F1 % W(1)*(P2(0)*(-1Q0)*(V3 % W(2)+CI*(V3 % - $ W(3)))+(P2(1)*(V3 % W(1)+V3 % W(4))+(P2(2)*(+CI*(V3 % W(1)+V3 - $ % W(4)))-P2(3)*(V3 % W(2)+CI*(V3 % W(3))))))+(F1 % W(2)*(P2(0) - $ *(-V3 % W(1)+V3 % W(4))+(P2(1)*(V3 % W(2)-CI*(V3 % W(3)))+(P2(2) - $ *(+CI*(V3 % W(2))+V3 % W(3))+P2(3)*(-V3 % W(1)+V3 % W(4)))))+M2 - $ *(F1 % W(3)*(V3 % W(2)+CI*(V3 % W(3)))-F1 % W(4)*(V3 % W(1)+V3 - $ % W(4))))) - F2%W(3)= COUP*(-CI)*(F1 % W(3)*(P2(0)*(-V3 % W(1)+V3 % W(4)) - $ +(P2(1)*(V3 % W(2)+CI*(V3 % W(3)))+(P2(2)*(-CI*(V3 % W(2))+V3 % - $ W(3))+P2(3)*(-V3 % W(1)+V3 % W(4)))))+(F1 % W(4)*(P2(0)*(V3 % - $ W(2)-CI*(V3 % W(3)))+(P2(1)*(-1Q0)*(V3 % W(1)+V3 % W(4))+(P2(2) - $ *(+CI*(V3 % W(1)+V3 % W(4)))+P2(3)*(V3 % W(2)-CI*(V3 % W(3)))))) - $ +M2*(F1 % W(1)*(-1Q0)*(V3 % W(1)+V3 % W(4))+F1 % W(2)*(-V3 % - $ W(2)+CI*(V3 % W(3)))))) - F2%W(4)= COUP*CI*(F1 % W(3)*(P2(0)*(-1Q0)*(V3 % W(2)+CI*(V3 % - $ W(3)))+(P2(1)*(V3 % W(1)-V3 % W(4))+(P2(2)*(+CI*(V3 % W(1))-CI - $ *(V3 % W(4)))+P2(3)*(V3 % W(2)+CI*(V3 % W(3))))))+(F1 % W(4) - $ *(P2(0)*(V3 % W(1)+V3 % W(4))+(P2(1)*(-V3 % W(2)+CI*(V3 % W(3))) - $ +(P2(2)*(-1Q0)*(+CI*(V3 % W(2))+V3 % W(3))-P2(3)*(V3 % W(1)+V3 - $ % W(4)))))+M2*(F1 % W(1)*(V3 % W(2)+CI*(V3 % W(3)))+F1 % W(2) - $ *(V3 % W(1)-V3 % W(4))))) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/MP_FFV1P0_3.f b/UNITTEST_proc/Source/DHELAS/MP_FFV1P0_3.f deleted file mode 100644 index 64bbad5858..0000000000 --- a/UNITTEST_proc/Source/DHELAS/MP_FFV1P0_3.f +++ /dev/null @@ -1,40 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C Gamma(3,2,1) -C - SUBROUTINE MP_FFV1P0_3(F1, F2, COUP, M3, W3,V3) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*32 CI - PARAMETER (CI=(0Q0,1Q0)) - COMPLEX*32 COUP - TYPE(MP_ALOHA) F1 - INTEGER FLV_INDEX1 - TYPE(MP_ALOHA) F2 - INTEGER FLV_INDEX2 - REAL*16 M3 - REAL*16 P3(0:3) - TYPE(MP_ALOHA) V3 - REAL*16 W3 - COMPLEX*32 DENOM - V3%P(:) = +F1%P(:)+F2%P(:) - P3(:) = -V3 % P (:) - FLV_INDEX1 = F1 %FLV_INDEX - FLV_INDEX2 = F2 %FLV_INDEX - IF(FLV_INDEX1.NE.FLV_INDEX2.OR.FLV_INDEX1.EQ.0)THEN - V3%W(:) = (0D0,0D0) - RETURN - ENDIF - DENOM = COUP/(P3(0)**2-P3(1)**2-P3(2)**2-P3(3)**2 - M3 * (M3 -CI - $ * W3)) - V3%W(1)= DENOM*(-CI)*(F2 % W(3)*F1 % W(1)+F2 % W(4)*F1 % W(2)+F2 - $ % W(1)*F1 % W(3)+F2 % W(2)*F1 % W(4)) - V3%W(2)= DENOM*(-CI)*(-F2 % W(4)*F1 % W(1)-F2 % W(3)*F1 % W(2) - $ +F2 % W(2)*F1 % W(3)+F2 % W(1)*F1 % W(4)) - V3%W(3)= DENOM*(-CI)*(-CI*(F2 % W(4)*F1 % W(1)+F2 % W(1)*F1 % - $ W(4))+CI*(F2 % W(3)*F1 % W(2)+F2 % W(2)*F1 % W(3))) - V3%W(4)= DENOM*(-CI)*(-F2 % W(3)*F1 % W(1)-F2 % W(2)*F1 % W(4) - $ +F2 % W(4)*F1 % W(2)+F2 % W(1)*F1 % W(3)) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/MP_FFV1_0.f b/UNITTEST_proc/Source/DHELAS/MP_FFV1_0.f deleted file mode 100644 index 83d839b2ad..0000000000 --- a/UNITTEST_proc/Source/DHELAS/MP_FFV1_0.f +++ /dev/null @@ -1,33 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C Gamma(3,2,1) -C - SUBROUTINE MP_FFV1_0(F1, F2, V3, COUP,VERTEX) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*32 CI - PARAMETER (CI=(0Q0,1Q0)) - COMPLEX*32 COUP - TYPE(MP_ALOHA) F1 - INTEGER FLV_INDEX1 - TYPE(MP_ALOHA) F2 - INTEGER FLV_INDEX2 - COMPLEX*32 TMP10 - TYPE(MP_ALOHA) V3 - COMPLEX*32 VERTEX - FLV_INDEX1 = F1 %FLV_INDEX - FLV_INDEX2 = F2 %FLV_INDEX - IF(FLV_INDEX1.NE.FLV_INDEX2.OR.FLV_INDEX1.EQ.0)THEN - VERTEX = (0D0,0D0) - RETURN - ENDIF - TMP10 = (F1 % W(1)*(F2 % W(3)*(V3 % W(1)+V3 % W(4))+F2 % W(4) - $ *(V3 % W(2)+CI*(V3 % W(3))))+(F1 % W(2)*(F2 % W(3)*(V3 % W(2) - $ -CI*(V3 % W(3)))+F2 % W(4)*(V3 % W(1)-V3 % W(4)))+(F1 % W(3) - $ *(F2 % W(1)*(V3 % W(1)-V3 % W(4))-F2 % W(2)*(V3 % W(2)+CI*(V3 % - $ W(3))))+F1 % W(4)*(F2 % W(1)*(-V3 % W(2)+CI*(V3 % W(3)))+F2 % - $ W(2)*(V3 % W(1)+V3 % W(4)))))) - VERTEX = COUP*(-CI * TMP10) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/MP_FFV1_1.f b/UNITTEST_proc/Source/DHELAS/MP_FFV1_1.f deleted file mode 100644 index b4489811e1..0000000000 --- a/UNITTEST_proc/Source/DHELAS/MP_FFV1_1.f +++ /dev/null @@ -1,55 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C Gamma(3,2,1) -C - SUBROUTINE MP_FFV1_1(F2, V3, COUP, M1, W1,F1) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*32 CI - PARAMETER (CI=(0Q0,1Q0)) - COMPLEX*32 COUP - TYPE(MP_ALOHA) F1 - INTEGER FLV_INDEX1 - TYPE(MP_ALOHA) F2 - INTEGER FLV_INDEX2 - REAL*16 M1 - REAL*16 P1(0:3) - TYPE(MP_ALOHA) V3 - REAL*16 W1 - COMPLEX*32 DENOM - F1%P(:) = +F2%P(:)+V3%P(:) - P1(:) = -F1 % P (:) - F1 % FLV_INDEX = F2 % FLV_INDEX - DENOM = COUP/(P1(0)**2-P1(1)**2-P1(2)**2-P1(3)**2 - M1 * (M1 -CI - $ * W1)) - F1%W(1)= DENOM*CI*(F2 % W(1)*(P1(0)*(-V3 % W(1)+V3 % W(4))+(P1(1) - $ *(V3 % W(2)-CI*(V3 % W(3)))+(P1(2)*(+CI*(V3 % W(2))+V3 % W(3)) - $ +P1(3)*(-V3 % W(1)+V3 % W(4)))))+(F2 % W(2)*(P1(0)*(V3 % W(2) - $ +CI*(V3 % W(3)))+(P1(1)*(-1Q0)*(V3 % W(1)+V3 % W(4))+(P1(2)*( - $ -1Q0)*(+CI*(V3 % W(1)+V3 % W(4)))+P1(3)*(V3 % W(2)+CI*(V3 % W(3) - $ )))))+M1*(F2 % W(3)*(V3 % W(1)+V3 % W(4))+F2 % W(4)*(V3 % W(2) - $ +CI*(V3 % W(3)))))) - F1%W(2)= DENOM*(-CI)*(F2 % W(1)*(P1(0)*(-V3 % W(2)+CI*(V3 % W(3)) - $ )+(P1(1)*(V3 % W(1)-V3 % W(4))+(P1(2)*(-CI*(V3 % W(1))+CI*(V3 % - $ W(4)))+P1(3)*(V3 % W(2)-CI*(V3 % W(3))))))+(F2 % W(2)*(P1(0) - $ *(V3 % W(1)+V3 % W(4))+(P1(1)*(-1Q0)*(V3 % W(2)+CI*(V3 % W(3))) - $ +(P1(2)*(+CI*(V3 % W(2))-V3 % W(3))-P1(3)*(V3 % W(1)+V3 % W(4))) - $ ))+M1*(F2 % W(3)*(-V3 % W(2)+CI*(V3 % W(3)))+F2 % W(4)*(-V3 % - $ W(1)+V3 % W(4))))) - F1%W(3)= DENOM*(-CI)*(F2 % W(3)*(P1(0)*(V3 % W(1)+V3 % W(4)) - $ +(P1(1)*(-V3 % W(2)+CI*(V3 % W(3)))+(P1(2)*(-1Q0)*(+CI*(V3 % - $ W(2))+V3 % W(3))-P1(3)*(V3 % W(1)+V3 % W(4)))))+(F2 % W(4) - $ *(P1(0)*(V3 % W(2)+CI*(V3 % W(3)))+(P1(1)*(-V3 % W(1)+V3 % W(4)) - $ +(P1(2)*(-CI*(V3 % W(1))+CI*(V3 % W(4)))-P1(3)*(V3 % W(2)+CI - $ *(V3 % W(3))))))+M1*(F2 % W(1)*(-V3 % W(1)+V3 % W(4))+F2 % W(2) - $ *(V3 % W(2)+CI*(V3 % W(3)))))) - F1%W(4)= DENOM*CI*(F2 % W(3)*(P1(0)*(-V3 % W(2)+CI*(V3 % W(3))) - $ +(P1(1)*(V3 % W(1)+V3 % W(4))+(P1(2)*(-1Q0)*(+CI*(V3 % W(1)+V3 - $ % W(4)))+P1(3)*(-V3 % W(2)+CI*(V3 % W(3))))))+(F2 % W(4)*(P1(0) - $ *(-V3 % W(1)+V3 % W(4))+(P1(1)*(V3 % W(2)+CI*(V3 % W(3)))+(P1(2) - $ *(-CI*(V3 % W(2))+V3 % W(3))+P1(3)*(-V3 % W(1)+V3 % W(4)))))+M1 - $ *(F2 % W(1)*(-V3 % W(2)+CI*(V3 % W(3)))+F2 % W(2)*(V3 % W(1)+V3 - $ % W(4))))) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/MP_FFV1_2.f b/UNITTEST_proc/Source/DHELAS/MP_FFV1_2.f deleted file mode 100644 index 1b1025ee3b..0000000000 --- a/UNITTEST_proc/Source/DHELAS/MP_FFV1_2.f +++ /dev/null @@ -1,55 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C Gamma(3,2,1) -C - SUBROUTINE MP_FFV1_2(F1, V3, COUP, M2, W2,F2) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*32 CI - PARAMETER (CI=(0Q0,1Q0)) - COMPLEX*32 COUP - TYPE(MP_ALOHA) F1 - INTEGER FLV_INDEX1 - TYPE(MP_ALOHA) F2 - INTEGER FLV_INDEX2 - REAL*16 M2 - REAL*16 P2(0:3) - TYPE(MP_ALOHA) V3 - REAL*16 W2 - COMPLEX*32 DENOM - F2%P(:) = +F1%P(:)+V3%P(:) - P2(:) = -F2 % P (:) - F2 % FLV_INDEX = F1 % FLV_INDEX - DENOM = COUP/(P2(0)**2-P2(1)**2-P2(2)**2-P2(3)**2 - M2 * (M2 -CI - $ * W2)) - F2%W(1)= DENOM*CI*(F1 % W(1)*(P2(0)*(V3 % W(1)+V3 % W(4))+(P2(1) - $ *(-1Q0)*(V3 % W(2)+CI*(V3 % W(3)))+(P2(2)*(+CI*(V3 % W(2))-V3 % - $ W(3))-P2(3)*(V3 % W(1)+V3 % W(4)))))+(F1 % W(2)*(P2(0)*(V3 % - $ W(2)-CI*(V3 % W(3)))+(P2(1)*(-V3 % W(1)+V3 % W(4))+(P2(2)*(+CI - $ *(V3 % W(1))-CI*(V3 % W(4)))+P2(3)*(-V3 % W(2)+CI*(V3 % W(3))))) - $ )+M2*(F1 % W(3)*(V3 % W(1)-V3 % W(4))+F1 % W(4)*(-V3 % W(2)+CI - $ *(V3 % W(3)))))) - F2%W(2)= DENOM*(-CI)*(F1 % W(1)*(P2(0)*(-1Q0)*(V3 % W(2)+CI*(V3 - $ % W(3)))+(P2(1)*(V3 % W(1)+V3 % W(4))+(P2(2)*(+CI*(V3 % W(1) - $ +V3 % W(4)))-P2(3)*(V3 % W(2)+CI*(V3 % W(3))))))+(F1 % W(2) - $ *(P2(0)*(-V3 % W(1)+V3 % W(4))+(P2(1)*(V3 % W(2)-CI*(V3 % W(3))) - $ +(P2(2)*(+CI*(V3 % W(2))+V3 % W(3))+P2(3)*(-V3 % W(1)+V3 % W(4)) - $ )))+M2*(F1 % W(3)*(V3 % W(2)+CI*(V3 % W(3)))-F1 % W(4)*(V3 % - $ W(1)+V3 % W(4))))) - F2%W(3)= DENOM*(-CI)*(F1 % W(3)*(P2(0)*(-V3 % W(1)+V3 % W(4)) - $ +(P2(1)*(V3 % W(2)+CI*(V3 % W(3)))+(P2(2)*(-CI*(V3 % W(2))+V3 % - $ W(3))+P2(3)*(-V3 % W(1)+V3 % W(4)))))+(F1 % W(4)*(P2(0)*(V3 % - $ W(2)-CI*(V3 % W(3)))+(P2(1)*(-1Q0)*(V3 % W(1)+V3 % W(4))+(P2(2) - $ *(+CI*(V3 % W(1)+V3 % W(4)))+P2(3)*(V3 % W(2)-CI*(V3 % W(3)))))) - $ +M2*(F1 % W(1)*(-1Q0)*(V3 % W(1)+V3 % W(4))+F1 % W(2)*(-V3 % - $ W(2)+CI*(V3 % W(3)))))) - F2%W(4)= DENOM*CI*(F1 % W(3)*(P2(0)*(-1Q0)*(V3 % W(2)+CI*(V3 % - $ W(3)))+(P2(1)*(V3 % W(1)-V3 % W(4))+(P2(2)*(+CI*(V3 % W(1))-CI - $ *(V3 % W(4)))+P2(3)*(V3 % W(2)+CI*(V3 % W(3))))))+(F1 % W(4) - $ *(P2(0)*(V3 % W(1)+V3 % W(4))+(P2(1)*(-V3 % W(2)+CI*(V3 % W(3))) - $ +(P2(2)*(-1Q0)*(+CI*(V3 % W(2))+V3 % W(3))-P2(3)*(V3 % W(1)+V3 - $ % W(4)))))+M2*(F1 % W(1)*(V3 % W(2)+CI*(V3 % W(3)))+F1 % W(2) - $ *(V3 % W(1)-V3 % W(4))))) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/MP_GHGHGL_1.f b/UNITTEST_proc/Source/DHELAS/MP_GHGHGL_1.f deleted file mode 100644 index 6b7a30b06b..0000000000 --- a/UNITTEST_proc/Source/DHELAS/MP_GHGHGL_1.f +++ /dev/null @@ -1,25 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C P(3,2) -C - SUBROUTINE MP_GHGHGL_1(S2, V3, COUP, M1, W1,S1) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*32 CI - PARAMETER (CI=(0Q0,1Q0)) - COMPLEX*32 COUP - REAL*16 M1 - COMPLEX*32 P2(0:3) - TYPE(MP_ALOHA) S1 - TYPE(MP_ALOHA) S2 - COMPLEX*32 TMP1 - TYPE(MP_ALOHA) V3 - REAL*16 W1 - P2(:) = S2 % P (:) - S1%P(:) = +S2%P(:)+V3%P(:) - TMP1 = (V3 % W(1)*P2(0)-V3 % W(2)*P2(1)-V3 % W(3)*P2(2)-V3 % W(4) - $ *P2(3)) - S1%W(1)= COUP*CI * TMP1*S2 % W(1) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/MP_GHGHGL_2.f b/UNITTEST_proc/Source/DHELAS/MP_GHGHGL_2.f deleted file mode 100644 index 86b662cbb3..0000000000 --- a/UNITTEST_proc/Source/DHELAS/MP_GHGHGL_2.f +++ /dev/null @@ -1,25 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C P(3,2) -C - SUBROUTINE MP_GHGHGL_2(S1, V3, COUP, M2, W2,S2) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*32 CI - PARAMETER (CI=(0Q0,1Q0)) - COMPLEX*32 COUP - REAL*16 M2 - COMPLEX*32 P2(0:3) - TYPE(MP_ALOHA) S1 - TYPE(MP_ALOHA) S2 - COMPLEX*32 TMP1 - TYPE(MP_ALOHA) V3 - REAL*16 W2 - S2%P(:) = +S1%P(:)+V3%P(:) - P2(:) = -S2 % P (:) - TMP1 = (V3 % W(1)*P2(0)-V3 % W(2)*P2(1)-V3 % W(3)*P2(2)-V3 % W(4) - $ *P2(3)) - S2%W(1)= COUP*CI * TMP1*S1 % W(1) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/MP_R2_GG_1_0.f b/UNITTEST_proc/Source/DHELAS/MP_R2_GG_1_0.f deleted file mode 100644 index 7c1716a229..0000000000 --- a/UNITTEST_proc/Source/DHELAS/MP_R2_GG_1_0.f +++ /dev/null @@ -1,24 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C P(-1,1)*P(-1,1)*Metric(1,2) -C - SUBROUTINE MP_R2_GG_1_0(V1, V2, COUP,VERTEX) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*32 CI - PARAMETER (CI=(0Q0,1Q0)) - COMPLEX*32 COUP - REAL*16 P1(0:3) - COMPLEX*32 TMP12 - COMPLEX*32 TMP3 - TYPE(MP_ALOHA) V1 - TYPE(MP_ALOHA) V2 - COMPLEX*32 VERTEX - P1(:) = V1 % P (:) - TMP12 = (P1(0)*P1(0)-P1(1)*P1(1)-P1(2)*P1(2)-P1(3)*P1(3)) - TMP3 = (V2 % W(1)*V1 % W(1)-V2 % W(2)*V1 % W(2)-V2 % W(3)*V1 % - $ W(3)-V2 % W(4)*V1 % W(4)) - VERTEX = COUP*(-CI * TMP3*TMP12) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/MP_R2_GG_1_R2_GG_2_0.f b/UNITTEST_proc/Source/DHELAS/MP_R2_GG_1_R2_GG_2_0.f deleted file mode 100644 index 2e22a66857..0000000000 --- a/UNITTEST_proc/Source/DHELAS/MP_R2_GG_1_R2_GG_2_0.f +++ /dev/null @@ -1,31 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -Coup(1) * (P(-1,1)*P(-1,1)*Metric(1,2)) + Coup(2) * (P(1,1)*P(2,1)) -C - SUBROUTINE MP_R2_GG_1_R2_GG_2_0(V1, V2, COUP1, COUP2,VERTEX) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*32 CI - PARAMETER (CI=(0Q0,1Q0)) - COMPLEX*32 COUP1 - COMPLEX*32 COUP2 - REAL*16 P1(0:3) - COMPLEX*32 TMP12 - COMPLEX*32 TMP13 - COMPLEX*32 TMP3 - COMPLEX*32 TMP5 - TYPE(MP_ALOHA) V1 - TYPE(MP_ALOHA) V2 - COMPLEX*32 VERTEX - P1(:) = V1 % P (:) - TMP12 = (P1(0)*P1(0)-P1(1)*P1(1)-P1(2)*P1(2)-P1(3)*P1(3)) - TMP13 = (P1(0)*V1 % W(1)-P1(1)*V1 % W(2)-P1(2)*V1 % W(3)-P1(3) - $ *V1 % W(4)) - TMP3 = (V2 % W(1)*V1 % W(1)-V2 % W(2)*V1 % W(2)-V2 % W(3)*V1 % - $ W(3)-V2 % W(4)*V1 % W(4)) - TMP5 = (V2 % W(1)*P1(0)-V2 % W(2)*P1(1)-V2 % W(3)*P1(2)-V2 % W(4) - $ *P1(3)) - VERTEX = (-1Q0)*(+CI*(TMP3*TMP12*COUP1+TMP5*TMP13*COUP2)) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/MP_R2_GG_1_R2_GG_3_0.f b/UNITTEST_proc/Source/DHELAS/MP_R2_GG_1_R2_GG_3_0.f deleted file mode 100644 index bc0230d8be..0000000000 --- a/UNITTEST_proc/Source/DHELAS/MP_R2_GG_1_R2_GG_3_0.f +++ /dev/null @@ -1,25 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -Coup(1) * (P(-1,1)*P(-1,1)*Metric(1,2)) + Coup(2) * (Metric(1,2)) -C - SUBROUTINE MP_R2_GG_1_R2_GG_3_0(V1, V2, COUP1, COUP2,VERTEX) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*32 CI - PARAMETER (CI=(0Q0,1Q0)) - COMPLEX*32 COUP1 - COMPLEX*32 COUP2 - REAL*16 P1(0:3) - COMPLEX*32 TMP12 - COMPLEX*32 TMP3 - TYPE(MP_ALOHA) V1 - TYPE(MP_ALOHA) V2 - COMPLEX*32 VERTEX - P1(:) = V1 % P (:) - TMP12 = (P1(0)*P1(0)-P1(1)*P1(1)-P1(2)*P1(2)-P1(3)*P1(3)) - TMP3 = (V2 % W(1)*V1 % W(1)-V2 % W(2)*V1 % W(2)-V2 % W(3)*V1 % - $ W(3)-V2 % W(4)*V1 % W(4)) - VERTEX = -TMP3*(+CI*(TMP12*COUP1+COUP2)) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/MP_R2_GG_2_0.f b/UNITTEST_proc/Source/DHELAS/MP_R2_GG_2_0.f deleted file mode 100644 index 859a9815e7..0000000000 --- a/UNITTEST_proc/Source/DHELAS/MP_R2_GG_2_0.f +++ /dev/null @@ -1,25 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C P(1,1)*P(2,1) -C - SUBROUTINE MP_R2_GG_2_0(V1, V2, COUP,VERTEX) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*32 CI - PARAMETER (CI=(0Q0,1Q0)) - COMPLEX*32 COUP - REAL*16 P1(0:3) - COMPLEX*32 TMP13 - COMPLEX*32 TMP5 - TYPE(MP_ALOHA) V1 - TYPE(MP_ALOHA) V2 - COMPLEX*32 VERTEX - P1(:) = V1 % P (:) - TMP13 = (P1(0)*V1 % W(1)-P1(1)*V1 % W(2)-P1(2)*V1 % W(3)-P1(3) - $ *V1 % W(4)) - TMP5 = (V2 % W(1)*P1(0)-V2 % W(2)*P1(1)-V2 % W(3)*P1(2)-V2 % W(4) - $ *P1(3)) - VERTEX = COUP*(-CI * TMP5*TMP13) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/MP_R2_GG_3_0.f b/UNITTEST_proc/Source/DHELAS/MP_R2_GG_3_0.f deleted file mode 100644 index bc59c0387b..0000000000 --- a/UNITTEST_proc/Source/DHELAS/MP_R2_GG_3_0.f +++ /dev/null @@ -1,20 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C Metric(1,2) -C - SUBROUTINE MP_R2_GG_3_0(V1, V2, COUP,VERTEX) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*32 CI - PARAMETER (CI=(0Q0,1Q0)) - COMPLEX*32 COUP - COMPLEX*32 TMP3 - TYPE(MP_ALOHA) V1 - TYPE(MP_ALOHA) V2 - COMPLEX*32 VERTEX - TMP3 = (V2 % W(1)*V1 % W(1)-V2 % W(2)*V1 % W(2)-V2 % W(3)*V1 % - $ W(3)-V2 % W(4)*V1 % W(4)) - VERTEX = COUP*(-CI * TMP3) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/MP_R2_QQ_1_0.f b/UNITTEST_proc/Source/DHELAS/MP_R2_QQ_1_0.f deleted file mode 100644 index 9e86ca3048..0000000000 --- a/UNITTEST_proc/Source/DHELAS/MP_R2_QQ_1_0.f +++ /dev/null @@ -1,33 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C P(-1,1)*Gamma(-1,2,1) -C - SUBROUTINE MP_R2_QQ_1_0(F1, F2, COUP,VERTEX) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*32 CI - PARAMETER (CI=(0Q0,1Q0)) - COMPLEX*32 COUP - TYPE(MP_ALOHA) F1 - INTEGER FLV_INDEX1 - TYPE(MP_ALOHA) F2 - INTEGER FLV_INDEX2 - REAL*16 P1(0:3) - COMPLEX*32 TMP14 - COMPLEX*32 VERTEX - P1(:) = F1 % P (:) - FLV_INDEX1 = F1 %FLV_INDEX - FLV_INDEX2 = F2 %FLV_INDEX - IF(FLV_INDEX1.NE.FLV_INDEX2.OR.FLV_INDEX1.EQ.0)THEN - VERTEX = (0D0,0D0) - RETURN - ENDIF - TMP14 = (F1 % W(1)*(F2 % W(3)*(P1(0)+P1(3))+F2 % W(4)*(P1(1)+CI - $ *(P1(2))))+(F1 % W(2)*(F2 % W(3)*(P1(1)-CI*(P1(2)))+F2 % W(4) - $ *(P1(0)-P1(3)))+(F1 % W(3)*(F2 % W(1)*(P1(0)-P1(3))-F2 % W(2) - $ *(P1(1)+CI*(P1(2))))+F1 % W(4)*(F2 % W(1)*(-P1(1)+CI*(P1(2))) - $ +F2 % W(2)*(P1(0)+P1(3)))))) - VERTEX = COUP*(-CI * TMP14) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/MP_R2_QQ_1_R2_QQ_2_0.f b/UNITTEST_proc/Source/DHELAS/MP_R2_QQ_1_R2_QQ_2_0.f deleted file mode 100644 index 59ab34f5fb..0000000000 --- a/UNITTEST_proc/Source/DHELAS/MP_R2_QQ_1_R2_QQ_2_0.f +++ /dev/null @@ -1,37 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -Coup(1) * (P(-1,1)*Gamma(-1,2,1)) + Coup(2) * (Identity(1,2)) -C - SUBROUTINE MP_R2_QQ_1_R2_QQ_2_0(F1, F2, COUP1, COUP2,VERTEX) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*32 CI - PARAMETER (CI=(0Q0,1Q0)) - COMPLEX*32 COUP1 - COMPLEX*32 COUP2 - TYPE(MP_ALOHA) F1 - INTEGER FLV_INDEX1 - TYPE(MP_ALOHA) F2 - INTEGER FLV_INDEX2 - REAL*16 P1(0:3) - COMPLEX*32 TMP15 - COMPLEX*32 TMP16 - COMPLEX*32 VERTEX - P1(:) = F1 % P (:) - FLV_INDEX1 = F1 %FLV_INDEX - FLV_INDEX2 = F2 %FLV_INDEX - IF(FLV_INDEX1.NE.FLV_INDEX2.OR.FLV_INDEX1.EQ.0)THEN - VERTEX = (0D0,0D0) - RETURN - ENDIF - TMP15 = (F2 % W(1)*F1 % W(1)+F2 % W(2)*F1 % W(2)+F2 % W(3)*F1 % - $ W(3)+F2 % W(4)*F1 % W(4)) - TMP16 = (F1 % W(1)*(F2 % W(3)*(P1(0)+P1(3))+F2 % W(4)*(P1(1)+CI - $ *(P1(2))))+(F1 % W(2)*(F2 % W(3)*(P1(1)-CI*(P1(2)))+F2 % W(4) - $ *(P1(0)-P1(3)))+(F1 % W(3)*(F2 % W(1)*(P1(0)-P1(3))-F2 % W(2) - $ *(P1(1)+CI*(P1(2))))+F1 % W(4)*(F2 % W(1)*(-P1(1)+CI*(P1(2))) - $ +F2 % W(2)*(P1(0)+P1(3)))))) - VERTEX = (-1Q0)*(+CI*(COUP1*TMP16+TMP15*COUP2)) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/MP_R2_QQ_2_0.f b/UNITTEST_proc/Source/DHELAS/MP_R2_QQ_2_0.f deleted file mode 100644 index f499f9ddeb..0000000000 --- a/UNITTEST_proc/Source/DHELAS/MP_R2_QQ_2_0.f +++ /dev/null @@ -1,28 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C Identity(1,2) -C - SUBROUTINE MP_R2_QQ_2_0(F1, F2, COUP,VERTEX) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*32 CI - PARAMETER (CI=(0Q0,1Q0)) - COMPLEX*32 COUP - TYPE(MP_ALOHA) F1 - INTEGER FLV_INDEX1 - TYPE(MP_ALOHA) F2 - INTEGER FLV_INDEX2 - COMPLEX*32 TMP15 - COMPLEX*32 VERTEX - FLV_INDEX1 = F1 %FLV_INDEX - FLV_INDEX2 = F2 %FLV_INDEX - IF(FLV_INDEX1.NE.FLV_INDEX2.OR.FLV_INDEX1.EQ.0)THEN - VERTEX = (0D0,0D0) - RETURN - ENDIF - TMP15 = (F2 % W(1)*F1 % W(1)+F2 % W(2)*F1 % W(2)+F2 % W(3)*F1 % - $ W(3)+F2 % W(4)*F1 % W(4)) - VERTEX = COUP*(-CI * TMP15) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/MP_VVV1LP0_1.f b/UNITTEST_proc/Source/DHELAS/MP_VVV1LP0_1.f deleted file mode 100644 index 42b5bf02c9..0000000000 --- a/UNITTEST_proc/Source/DHELAS/MP_VVV1LP0_1.f +++ /dev/null @@ -1,49 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C P(3,1)*Metric(1,2) - P(3,2)*Metric(1,2) - P(2,1)*Metric(1,3) + -C P(2,3)*Metric(1,3) + P(1,2)*Metric(2,3) - P(1,3)*Metric(2,3) -C - SUBROUTINE MP_VVV1LP0_1(V2, V3, COUP, M1, W1,V1) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*32 CI - PARAMETER (CI=(0Q0,1Q0)) - COMPLEX*32 COUP - REAL*16 M1 - COMPLEX*32 P1(0:3) - COMPLEX*32 P2(0:3) - COMPLEX*32 P3(0:3) - COMPLEX*32 TMP0 - COMPLEX*32 TMP1 - COMPLEX*32 TMP5 - COMPLEX*32 TMP6 - COMPLEX*32 TMP8 - TYPE(MP_ALOHA) V1 - TYPE(MP_ALOHA) V2 - TYPE(MP_ALOHA) V3 - REAL*16 W1 - P2(:) = V2 % P (:) - P3(:) = V3 % P (:) - V1%P(:) = +V2%P(:)+V3%P(:) - P1(:) = -V1 % P (:) - TMP0 = (V3 % W(1)*P1(0)-V3 % W(2)*P1(1)-V3 % W(3)*P1(2)-V3 % W(4) - $ *P1(3)) - TMP1 = (V3 % W(1)*P2(0)-V3 % W(2)*P2(1)-V3 % W(3)*P2(2)-V3 % W(4) - $ *P2(3)) - TMP5 = (V2 % W(1)*P1(0)-V2 % W(2)*P1(1)-V2 % W(3)*P1(2)-V2 % W(4) - $ *P1(3)) - TMP6 = (V2 % W(1)*P3(0)-V2 % W(2)*P3(1)-V2 % W(3)*P3(2)-V2 % W(4) - $ *P3(3)) - TMP8 = (V2 % W(1)*V3 % W(1)-V2 % W(2)*V3 % W(2)-V2 % W(3)*V3 % - $ W(3)-V2 % W(4)*V3 % W(4)) - V1%W(1)= COUP*(TMP8*(-CI*(P2(0))+CI*(P3(0)))+(V2 % W(1)*(-CI - $ *(TMP0)+CI*(TMP1))+V3 % W(1)*(+CI*(TMP5)-CI*(TMP6)))) - V1%W(2)= COUP*(TMP8*(-CI*(P2(1))+CI*(P3(1)))+(V2 % W(2)*(-CI - $ *(TMP0)+CI*(TMP1))+V3 % W(2)*(+CI*(TMP5)-CI*(TMP6)))) - V1%W(3)= COUP*(TMP8*(-CI*(P2(2))+CI*(P3(2)))+(V2 % W(3)*(-CI - $ *(TMP0)+CI*(TMP1))+V3 % W(3)*(+CI*(TMP5)-CI*(TMP6)))) - V1%W(4)= COUP*(TMP8*(-CI*(P2(3))+CI*(P3(3)))+(V2 % W(4)*(-CI - $ *(TMP0)+CI*(TMP1))+V3 % W(4)*(+CI*(TMP5)-CI*(TMP6)))) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/MP_VVV1P0_1.f b/UNITTEST_proc/Source/DHELAS/MP_VVV1P0_1.f deleted file mode 100644 index 1e0ae5bda3..0000000000 --- a/UNITTEST_proc/Source/DHELAS/MP_VVV1P0_1.f +++ /dev/null @@ -1,52 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C P(3,1)*Metric(1,2) - P(3,2)*Metric(1,2) - P(2,1)*Metric(1,3) + -C P(2,3)*Metric(1,3) + P(1,2)*Metric(2,3) - P(1,3)*Metric(2,3) -C - SUBROUTINE MP_VVV1P0_1(V2, V3, COUP, M1, W1,V1) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*32 CI - PARAMETER (CI=(0Q0,1Q0)) - COMPLEX*32 COUP - REAL*16 M1 - REAL*16 P1(0:3) - REAL*16 P2(0:3) - REAL*16 P3(0:3) - COMPLEX*32 TMP0 - COMPLEX*32 TMP1 - COMPLEX*32 TMP5 - COMPLEX*32 TMP6 - COMPLEX*32 TMP8 - TYPE(MP_ALOHA) V1 - TYPE(MP_ALOHA) V2 - TYPE(MP_ALOHA) V3 - REAL*16 W1 - COMPLEX*32 DENOM - P2(:) = V2 % P (:) - P3(:) = V3 % P (:) - V1%P(:) = +V2%P(:)+V3%P(:) - P1(:) = -V1 % P (:) - TMP0 = (V3 % W(1)*P1(0)-V3 % W(2)*P1(1)-V3 % W(3)*P1(2)-V3 % W(4) - $ *P1(3)) - TMP1 = (V3 % W(1)*P2(0)-V3 % W(2)*P2(1)-V3 % W(3)*P2(2)-V3 % W(4) - $ *P2(3)) - TMP5 = (V2 % W(1)*P1(0)-V2 % W(2)*P1(1)-V2 % W(3)*P1(2)-V2 % W(4) - $ *P1(3)) - TMP6 = (V2 % W(1)*P3(0)-V2 % W(2)*P3(1)-V2 % W(3)*P3(2)-V2 % W(4) - $ *P3(3)) - TMP8 = (V2 % W(1)*V3 % W(1)-V2 % W(2)*V3 % W(2)-V2 % W(3)*V3 % - $ W(3)-V2 % W(4)*V3 % W(4)) - DENOM = COUP/(P1(0)**2-P1(1)**2-P1(2)**2-P1(3)**2 - M1 * (M1 -CI - $ * W1)) - V1%W(1)= DENOM*(TMP8*(-CI*(P2(0))+CI*(P3(0)))+(V2 % W(1)*(-CI - $ *(TMP0)+CI*(TMP1))+V3 % W(1)*(+CI*(TMP5)-CI*(TMP6)))) - V1%W(2)= DENOM*(TMP8*(-CI*(P2(1))+CI*(P3(1)))+(V2 % W(2)*(-CI - $ *(TMP0)+CI*(TMP1))+V3 % W(2)*(+CI*(TMP5)-CI*(TMP6)))) - V1%W(3)= DENOM*(TMP8*(-CI*(P2(2))+CI*(P3(2)))+(V2 % W(3)*(-CI - $ *(TMP0)+CI*(TMP1))+V3 % W(3)*(+CI*(TMP5)-CI*(TMP6)))) - V1%W(4)= DENOM*(TMP8*(-CI*(P2(3))+CI*(P3(3)))+(V2 % W(4)*(-CI - $ *(TMP0)+CI*(TMP1))+V3 % W(4)*(+CI*(TMP5)-CI*(TMP6)))) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/MP_VVV1_0.f b/UNITTEST_proc/Source/DHELAS/MP_VVV1_0.f deleted file mode 100644 index db92b4282c..0000000000 --- a/UNITTEST_proc/Source/DHELAS/MP_VVV1_0.f +++ /dev/null @@ -1,53 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C P(3,1)*Metric(1,2) - P(3,2)*Metric(1,2) - P(2,1)*Metric(1,3) + -C P(2,3)*Metric(1,3) + P(1,2)*Metric(2,3) - P(1,3)*Metric(2,3) -C - SUBROUTINE MP_VVV1_0(V1, V2, V3, COUP,VERTEX) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*32 CI - PARAMETER (CI=(0Q0,1Q0)) - COMPLEX*32 COUP - REAL*16 P1(0:3) - REAL*16 P2(0:3) - REAL*16 P3(0:3) - COMPLEX*32 TMP0 - COMPLEX*32 TMP1 - COMPLEX*32 TMP3 - COMPLEX*32 TMP4 - COMPLEX*32 TMP5 - COMPLEX*32 TMP6 - COMPLEX*32 TMP7 - COMPLEX*32 TMP8 - COMPLEX*32 TMP9 - TYPE(MP_ALOHA) V1 - TYPE(MP_ALOHA) V2 - TYPE(MP_ALOHA) V3 - COMPLEX*32 VERTEX - P1(:) = V1 % P (:) - P2(:) = V2 % P (:) - P3(:) = V3 % P (:) - TMP0 = (V3 % W(1)*P1(0)-V3 % W(2)*P1(1)-V3 % W(3)*P1(2)-V3 % W(4) - $ *P1(3)) - TMP1 = (V3 % W(1)*P2(0)-V3 % W(2)*P2(1)-V3 % W(3)*P2(2)-V3 % W(4) - $ *P2(3)) - TMP3 = (V2 % W(1)*V1 % W(1)-V2 % W(2)*V1 % W(2)-V2 % W(3)*V1 % - $ W(3)-V2 % W(4)*V1 % W(4)) - TMP4 = (V3 % W(1)*V1 % W(1)-V3 % W(2)*V1 % W(2)-V3 % W(3)*V1 % - $ W(3)-V3 % W(4)*V1 % W(4)) - TMP5 = (V2 % W(1)*P1(0)-V2 % W(2)*P1(1)-V2 % W(3)*P1(2)-V2 % W(4) - $ *P1(3)) - TMP6 = (V2 % W(1)*P3(0)-V2 % W(2)*P3(1)-V2 % W(3)*P3(2)-V2 % W(4) - $ *P3(3)) - TMP7 = (P2(0)*V1 % W(1)-P2(1)*V1 % W(2)-P2(2)*V1 % W(3)-P2(3)*V1 - $ % W(4)) - TMP8 = (V2 % W(1)*V3 % W(1)-V2 % W(2)*V3 % W(2)-V2 % W(3)*V3 % - $ W(3)-V2 % W(4)*V3 % W(4)) - TMP9 = (P3(0)*V1 % W(1)-P3(1)*V1 % W(2)-P3(2)*V1 % W(3)-P3(3)*V1 - $ % W(4)) - VERTEX = COUP*(TMP3*(-CI*(TMP0)+CI*(TMP1))+(TMP4*(+CI*(TMP5)-CI - $ *(TMP6))+TMP8*(-CI*(TMP7)+CI*(TMP9)))) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/MP_VVVV1LP0_1.f b/UNITTEST_proc/Source/DHELAS/MP_VVVV1LP0_1.f deleted file mode 100644 index 1eb5b5abd5..0000000000 --- a/UNITTEST_proc/Source/DHELAS/MP_VVVV1LP0_1.f +++ /dev/null @@ -1,30 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C Metric(1,4)*Metric(2,3) - Metric(1,3)*Metric(2,4) -C - SUBROUTINE MP_VVVV1LP0_1(V2, V3, V4, COUP, M1, W1,V1) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*32 CI - PARAMETER (CI=(0Q0,1Q0)) - COMPLEX*32 COUP - REAL*16 M1 - COMPLEX*32 TMP11 - COMPLEX*32 TMP8 - TYPE(MP_ALOHA) V1 - TYPE(MP_ALOHA) V2 - TYPE(MP_ALOHA) V3 - TYPE(MP_ALOHA) V4 - REAL*16 W1 - V1%P(:) = +V2%P(:)+V3%P(:)+V4%P(:) - TMP11 = (V2 % W(1)*V4 % W(1)-V2 % W(2)*V4 % W(2)-V2 % W(3)*V4 % - $ W(3)-V2 % W(4)*V4 % W(4)) - TMP8 = (V2 % W(1)*V3 % W(1)-V2 % W(2)*V3 % W(2)-V2 % W(3)*V3 % - $ W(3)-V2 % W(4)*V3 % W(4)) - V1%W(1)= COUP*(-CI*(V4 % W(1)*TMP8)+CI*(V3 % W(1)*TMP11)) - V1%W(2)= COUP*(-CI*(V4 % W(2)*TMP8)+CI*(V3 % W(2)*TMP11)) - V1%W(3)= COUP*(-CI*(V4 % W(3)*TMP8)+CI*(V3 % W(3)*TMP11)) - V1%W(4)= COUP*(-CI*(V4 % W(4)*TMP8)+CI*(V3 % W(4)*TMP11)) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/MP_VVVV3LP0_1.f b/UNITTEST_proc/Source/DHELAS/MP_VVVV3LP0_1.f deleted file mode 100644 index 9d29023cf0..0000000000 --- a/UNITTEST_proc/Source/DHELAS/MP_VVVV3LP0_1.f +++ /dev/null @@ -1,30 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C Metric(1,4)*Metric(2,3) - Metric(1,2)*Metric(3,4) -C - SUBROUTINE MP_VVVV3LP0_1(V2, V3, V4, COUP, M1, W1,V1) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*32 CI - PARAMETER (CI=(0Q0,1Q0)) - COMPLEX*32 COUP - REAL*16 M1 - COMPLEX*32 TMP2 - COMPLEX*32 TMP8 - TYPE(MP_ALOHA) V1 - TYPE(MP_ALOHA) V2 - TYPE(MP_ALOHA) V3 - TYPE(MP_ALOHA) V4 - REAL*16 W1 - V1%P(:) = +V2%P(:)+V3%P(:)+V4%P(:) - TMP2 = (V3 % W(1)*V4 % W(1)-V3 % W(2)*V4 % W(2)-V3 % W(3)*V4 % - $ W(3)-V3 % W(4)*V4 % W(4)) - TMP8 = (V2 % W(1)*V3 % W(1)-V2 % W(2)*V3 % W(2)-V2 % W(3)*V3 % - $ W(3)-V2 % W(4)*V3 % W(4)) - V1%W(1)= COUP*(-CI*(V4 % W(1)*TMP8)+CI*(V2 % W(1)*TMP2)) - V1%W(2)= COUP*(-CI*(V4 % W(2)*TMP8)+CI*(V2 % W(2)*TMP2)) - V1%W(3)= COUP*(-CI*(V4 % W(3)*TMP8)+CI*(V2 % W(3)*TMP2)) - V1%W(4)= COUP*(-CI*(V4 % W(4)*TMP8)+CI*(V2 % W(4)*TMP2)) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/MP_VVVV4LP0_1.f b/UNITTEST_proc/Source/DHELAS/MP_VVVV4LP0_1.f deleted file mode 100644 index 960037890a..0000000000 --- a/UNITTEST_proc/Source/DHELAS/MP_VVVV4LP0_1.f +++ /dev/null @@ -1,30 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C Metric(1,3)*Metric(2,4) - Metric(1,2)*Metric(3,4) -C - SUBROUTINE MP_VVVV4LP0_1(V2, V3, V4, COUP, M1, W1,V1) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*32 CI - PARAMETER (CI=(0Q0,1Q0)) - COMPLEX*32 COUP - REAL*16 M1 - COMPLEX*32 TMP11 - COMPLEX*32 TMP2 - TYPE(MP_ALOHA) V1 - TYPE(MP_ALOHA) V2 - TYPE(MP_ALOHA) V3 - TYPE(MP_ALOHA) V4 - REAL*16 W1 - V1%P(:) = +V2%P(:)+V3%P(:)+V4%P(:) - TMP11 = (V2 % W(1)*V4 % W(1)-V2 % W(2)*V4 % W(2)-V2 % W(3)*V4 % - $ W(3)-V2 % W(4)*V4 % W(4)) - TMP2 = (V3 % W(1)*V4 % W(1)-V3 % W(2)*V4 % W(2)-V3 % W(3)*V4 % - $ W(3)-V3 % W(4)*V4 % W(4)) - V1%W(1)= COUP*(-CI*(V3 % W(1)*TMP11)+CI*(V2 % W(1)*TMP2)) - V1%W(2)= COUP*(-CI*(V3 % W(2)*TMP11)+CI*(V2 % W(2)*TMP2)) - V1%W(3)= COUP*(-CI*(V3 % W(3)*TMP11)+CI*(V2 % W(3)*TMP2)) - V1%W(4)= COUP*(-CI*(V3 % W(4)*TMP11)+CI*(V2 % W(4)*TMP2)) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/R2_GG_1_0.f b/UNITTEST_proc/Source/DHELAS/R2_GG_1_0.f deleted file mode 100644 index 79ba6ed000..0000000000 --- a/UNITTEST_proc/Source/DHELAS/R2_GG_1_0.f +++ /dev/null @@ -1,24 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C P(-1,1)*P(-1,1)*Metric(1,2) -C - SUBROUTINE R2_GG_1_0(V1, V2, COUP,VERTEX) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*16 CI - PARAMETER (CI=(0D0,1D0)) - COMPLEX*16 COUP - REAL*8 P1(0:3) - COMPLEX*16 TMP12 - COMPLEX*16 TMP3 - TYPE(ALOHA) V1 - TYPE(ALOHA) V2 - COMPLEX*16 VERTEX - P1(:) = V1 % P (:) - TMP12 = (P1(0)*P1(0)-P1(1)*P1(1)-P1(2)*P1(2)-P1(3)*P1(3)) - TMP3 = (V2 % W(1)*V1 % W(1)-V2 % W(2)*V1 % W(2)-V2 % W(3)*V1 % - $ W(3)-V2 % W(4)*V1 % W(4)) - VERTEX = COUP*(-CI * TMP3*TMP12) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/R2_GG_1_R2_GG_2_0.f b/UNITTEST_proc/Source/DHELAS/R2_GG_1_R2_GG_2_0.f deleted file mode 100644 index 2cb5ba766e..0000000000 --- a/UNITTEST_proc/Source/DHELAS/R2_GG_1_R2_GG_2_0.f +++ /dev/null @@ -1,31 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -Coup(1) * (P(-1,1)*P(-1,1)*Metric(1,2)) + Coup(2) * (P(1,1)*P(2,1)) -C - SUBROUTINE R2_GG_1_R2_GG_2_0(V1, V2, COUP1, COUP2,VERTEX) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*16 CI - PARAMETER (CI=(0D0,1D0)) - COMPLEX*16 COUP1 - COMPLEX*16 COUP2 - REAL*8 P1(0:3) - COMPLEX*16 TMP12 - COMPLEX*16 TMP13 - COMPLEX*16 TMP3 - COMPLEX*16 TMP5 - TYPE(ALOHA) V1 - TYPE(ALOHA) V2 - COMPLEX*16 VERTEX - P1(:) = V1 % P (:) - TMP12 = (P1(0)*P1(0)-P1(1)*P1(1)-P1(2)*P1(2)-P1(3)*P1(3)) - TMP13 = (P1(0)*V1 % W(1)-P1(1)*V1 % W(2)-P1(2)*V1 % W(3)-P1(3) - $ *V1 % W(4)) - TMP3 = (V2 % W(1)*V1 % W(1)-V2 % W(2)*V1 % W(2)-V2 % W(3)*V1 % - $ W(3)-V2 % W(4)*V1 % W(4)) - TMP5 = (V2 % W(1)*P1(0)-V2 % W(2)*P1(1)-V2 % W(3)*P1(2)-V2 % W(4) - $ *P1(3)) - VERTEX = (-1D0)*(+CI*(TMP3*TMP12*COUP1+TMP5*TMP13*COUP2)) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/R2_GG_1_R2_GG_3_0.f b/UNITTEST_proc/Source/DHELAS/R2_GG_1_R2_GG_3_0.f deleted file mode 100644 index b5a7aa5c89..0000000000 --- a/UNITTEST_proc/Source/DHELAS/R2_GG_1_R2_GG_3_0.f +++ /dev/null @@ -1,25 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -Coup(1) * (P(-1,1)*P(-1,1)*Metric(1,2)) + Coup(2) * (Metric(1,2)) -C - SUBROUTINE R2_GG_1_R2_GG_3_0(V1, V2, COUP1, COUP2,VERTEX) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*16 CI - PARAMETER (CI=(0D0,1D0)) - COMPLEX*16 COUP1 - COMPLEX*16 COUP2 - REAL*8 P1(0:3) - COMPLEX*16 TMP12 - COMPLEX*16 TMP3 - TYPE(ALOHA) V1 - TYPE(ALOHA) V2 - COMPLEX*16 VERTEX - P1(:) = V1 % P (:) - TMP12 = (P1(0)*P1(0)-P1(1)*P1(1)-P1(2)*P1(2)-P1(3)*P1(3)) - TMP3 = (V2 % W(1)*V1 % W(1)-V2 % W(2)*V1 % W(2)-V2 % W(3)*V1 % - $ W(3)-V2 % W(4)*V1 % W(4)) - VERTEX = -TMP3*(+CI*(TMP12*COUP1+COUP2)) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/R2_GG_2_0.f b/UNITTEST_proc/Source/DHELAS/R2_GG_2_0.f deleted file mode 100644 index 663bbc2cc6..0000000000 --- a/UNITTEST_proc/Source/DHELAS/R2_GG_2_0.f +++ /dev/null @@ -1,25 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C P(1,1)*P(2,1) -C - SUBROUTINE R2_GG_2_0(V1, V2, COUP,VERTEX) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*16 CI - PARAMETER (CI=(0D0,1D0)) - COMPLEX*16 COUP - REAL*8 P1(0:3) - COMPLEX*16 TMP13 - COMPLEX*16 TMP5 - TYPE(ALOHA) V1 - TYPE(ALOHA) V2 - COMPLEX*16 VERTEX - P1(:) = V1 % P (:) - TMP13 = (P1(0)*V1 % W(1)-P1(1)*V1 % W(2)-P1(2)*V1 % W(3)-P1(3) - $ *V1 % W(4)) - TMP5 = (V2 % W(1)*P1(0)-V2 % W(2)*P1(1)-V2 % W(3)*P1(2)-V2 % W(4) - $ *P1(3)) - VERTEX = COUP*(-CI * TMP5*TMP13) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/R2_GG_3_0.f b/UNITTEST_proc/Source/DHELAS/R2_GG_3_0.f deleted file mode 100644 index 3a3edb5bd7..0000000000 --- a/UNITTEST_proc/Source/DHELAS/R2_GG_3_0.f +++ /dev/null @@ -1,20 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C Metric(1,2) -C - SUBROUTINE R2_GG_3_0(V1, V2, COUP,VERTEX) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*16 CI - PARAMETER (CI=(0D0,1D0)) - COMPLEX*16 COUP - COMPLEX*16 TMP3 - TYPE(ALOHA) V1 - TYPE(ALOHA) V2 - COMPLEX*16 VERTEX - TMP3 = (V2 % W(1)*V1 % W(1)-V2 % W(2)*V1 % W(2)-V2 % W(3)*V1 % - $ W(3)-V2 % W(4)*V1 % W(4)) - VERTEX = COUP*(-CI * TMP3) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/R2_QQ_1_0.f b/UNITTEST_proc/Source/DHELAS/R2_QQ_1_0.f deleted file mode 100644 index 4be3fea115..0000000000 --- a/UNITTEST_proc/Source/DHELAS/R2_QQ_1_0.f +++ /dev/null @@ -1,33 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C P(-1,1)*Gamma(-1,2,1) -C - SUBROUTINE R2_QQ_1_0(F1, F2, COUP,VERTEX) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*16 CI - PARAMETER (CI=(0D0,1D0)) - COMPLEX*16 COUP - TYPE(ALOHA) F1 - INTEGER FLV_INDEX1 - TYPE(ALOHA) F2 - INTEGER FLV_INDEX2 - REAL*8 P1(0:3) - COMPLEX*16 TMP14 - COMPLEX*16 VERTEX - P1(:) = F1 % P (:) - FLV_INDEX1 = F1 %FLV_INDEX - FLV_INDEX2 = F2 %FLV_INDEX - IF(FLV_INDEX1.NE.FLV_INDEX2.OR.FLV_INDEX1.EQ.0)THEN - VERTEX = (0D0,0D0) - RETURN - ENDIF - TMP14 = (F1 % W(1)*(F2 % W(3)*(P1(0)+P1(3))+F2 % W(4)*(P1(1)+CI - $ *(P1(2))))+(F1 % W(2)*(F2 % W(3)*(P1(1)-CI*(P1(2)))+F2 % W(4) - $ *(P1(0)-P1(3)))+(F1 % W(3)*(F2 % W(1)*(P1(0)-P1(3))-F2 % W(2) - $ *(P1(1)+CI*(P1(2))))+F1 % W(4)*(F2 % W(1)*(-P1(1)+CI*(P1(2))) - $ +F2 % W(2)*(P1(0)+P1(3)))))) - VERTEX = COUP*(-CI * TMP14) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/R2_QQ_1_R2_QQ_2_0.f b/UNITTEST_proc/Source/DHELAS/R2_QQ_1_R2_QQ_2_0.f deleted file mode 100644 index 566ac0dd08..0000000000 --- a/UNITTEST_proc/Source/DHELAS/R2_QQ_1_R2_QQ_2_0.f +++ /dev/null @@ -1,37 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -Coup(1) * (P(-1,1)*Gamma(-1,2,1)) + Coup(2) * (Identity(1,2)) -C - SUBROUTINE R2_QQ_1_R2_QQ_2_0(F1, F2, COUP1, COUP2,VERTEX) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*16 CI - PARAMETER (CI=(0D0,1D0)) - COMPLEX*16 COUP1 - COMPLEX*16 COUP2 - TYPE(ALOHA) F1 - INTEGER FLV_INDEX1 - TYPE(ALOHA) F2 - INTEGER FLV_INDEX2 - REAL*8 P1(0:3) - COMPLEX*16 TMP15 - COMPLEX*16 TMP16 - COMPLEX*16 VERTEX - P1(:) = F1 % P (:) - FLV_INDEX1 = F1 %FLV_INDEX - FLV_INDEX2 = F2 %FLV_INDEX - IF(FLV_INDEX1.NE.FLV_INDEX2.OR.FLV_INDEX1.EQ.0)THEN - VERTEX = (0D0,0D0) - RETURN - ENDIF - TMP15 = (F2 % W(1)*F1 % W(1)+F2 % W(2)*F1 % W(2)+F2 % W(3)*F1 % - $ W(3)+F2 % W(4)*F1 % W(4)) - TMP16 = (F1 % W(1)*(F2 % W(3)*(P1(0)+P1(3))+F2 % W(4)*(P1(1)+CI - $ *(P1(2))))+(F1 % W(2)*(F2 % W(3)*(P1(1)-CI*(P1(2)))+F2 % W(4) - $ *(P1(0)-P1(3)))+(F1 % W(3)*(F2 % W(1)*(P1(0)-P1(3))-F2 % W(2) - $ *(P1(1)+CI*(P1(2))))+F1 % W(4)*(F2 % W(1)*(-P1(1)+CI*(P1(2))) - $ +F2 % W(2)*(P1(0)+P1(3)))))) - VERTEX = (-1D0)*(+CI*(COUP1*TMP16+TMP15*COUP2)) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/R2_QQ_2_0.f b/UNITTEST_proc/Source/DHELAS/R2_QQ_2_0.f deleted file mode 100644 index 07d6cd4ff1..0000000000 --- a/UNITTEST_proc/Source/DHELAS/R2_QQ_2_0.f +++ /dev/null @@ -1,28 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C Identity(1,2) -C - SUBROUTINE R2_QQ_2_0(F1, F2, COUP,VERTEX) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*16 CI - PARAMETER (CI=(0D0,1D0)) - COMPLEX*16 COUP - TYPE(ALOHA) F1 - INTEGER FLV_INDEX1 - TYPE(ALOHA) F2 - INTEGER FLV_INDEX2 - COMPLEX*16 TMP15 - COMPLEX*16 VERTEX - FLV_INDEX1 = F1 %FLV_INDEX - FLV_INDEX2 = F2 %FLV_INDEX - IF(FLV_INDEX1.NE.FLV_INDEX2.OR.FLV_INDEX1.EQ.0)THEN - VERTEX = (0D0,0D0) - RETURN - ENDIF - TMP15 = (F2 % W(1)*F1 % W(1)+F2 % W(2)*F1 % W(2)+F2 % W(3)*F1 % - $ W(3)+F2 % W(4)*F1 % W(4)) - VERTEX = COUP*(-CI * TMP15) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/VVV1LP0_1.f b/UNITTEST_proc/Source/DHELAS/VVV1LP0_1.f deleted file mode 100644 index ef3a9f1d45..0000000000 --- a/UNITTEST_proc/Source/DHELAS/VVV1LP0_1.f +++ /dev/null @@ -1,49 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C P(3,1)*Metric(1,2) - P(3,2)*Metric(1,2) - P(2,1)*Metric(1,3) + -C P(2,3)*Metric(1,3) + P(1,2)*Metric(2,3) - P(1,3)*Metric(2,3) -C - SUBROUTINE VVV1LP0_1(V2, V3, COUP, M1, W1,V1) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*16 CI - PARAMETER (CI=(0D0,1D0)) - COMPLEX*16 COUP - REAL*8 M1 - COMPLEX*16 P1(0:3) - COMPLEX*16 P2(0:3) - COMPLEX*16 P3(0:3) - COMPLEX*16 TMP0 - COMPLEX*16 TMP1 - COMPLEX*16 TMP5 - COMPLEX*16 TMP6 - COMPLEX*16 TMP8 - TYPE(ALOHA) V1 - TYPE(ALOHA) V2 - TYPE(ALOHA) V3 - REAL*8 W1 - P2(:) = V2 % P (:) - P3(:) = V3 % P (:) - V1%P(:) = +V2%P(:)+V3%P(:) - P1(:) = -V1 % P (:) - TMP0 = (V3 % W(1)*P1(0)-V3 % W(2)*P1(1)-V3 % W(3)*P1(2)-V3 % W(4) - $ *P1(3)) - TMP1 = (V3 % W(1)*P2(0)-V3 % W(2)*P2(1)-V3 % W(3)*P2(2)-V3 % W(4) - $ *P2(3)) - TMP5 = (V2 % W(1)*P1(0)-V2 % W(2)*P1(1)-V2 % W(3)*P1(2)-V2 % W(4) - $ *P1(3)) - TMP6 = (V2 % W(1)*P3(0)-V2 % W(2)*P3(1)-V2 % W(3)*P3(2)-V2 % W(4) - $ *P3(3)) - TMP8 = (V2 % W(1)*V3 % W(1)-V2 % W(2)*V3 % W(2)-V2 % W(3)*V3 % - $ W(3)-V2 % W(4)*V3 % W(4)) - V1%W(1)= COUP*(TMP8*(-CI*(P2(0))+CI*(P3(0)))+(V2 % W(1)*(-CI - $ *(TMP0)+CI*(TMP1))+V3 % W(1)*(+CI*(TMP5)-CI*(TMP6)))) - V1%W(2)= COUP*(TMP8*(-CI*(P2(1))+CI*(P3(1)))+(V2 % W(2)*(-CI - $ *(TMP0)+CI*(TMP1))+V3 % W(2)*(+CI*(TMP5)-CI*(TMP6)))) - V1%W(3)= COUP*(TMP8*(-CI*(P2(2))+CI*(P3(2)))+(V2 % W(3)*(-CI - $ *(TMP0)+CI*(TMP1))+V3 % W(3)*(+CI*(TMP5)-CI*(TMP6)))) - V1%W(4)= COUP*(TMP8*(-CI*(P2(3))+CI*(P3(3)))+(V2 % W(4)*(-CI - $ *(TMP0)+CI*(TMP1))+V3 % W(4)*(+CI*(TMP5)-CI*(TMP6)))) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/VVV1P0_1.f b/UNITTEST_proc/Source/DHELAS/VVV1P0_1.f deleted file mode 100644 index e45def8ee7..0000000000 --- a/UNITTEST_proc/Source/DHELAS/VVV1P0_1.f +++ /dev/null @@ -1,52 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C P(3,1)*Metric(1,2) - P(3,2)*Metric(1,2) - P(2,1)*Metric(1,3) + -C P(2,3)*Metric(1,3) + P(1,2)*Metric(2,3) - P(1,3)*Metric(2,3) -C - SUBROUTINE VVV1P0_1(V2, V3, COUP, M1, W1,V1) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*16 CI - PARAMETER (CI=(0D0,1D0)) - COMPLEX*16 COUP - REAL*8 M1 - REAL*8 P1(0:3) - REAL*8 P2(0:3) - REAL*8 P3(0:3) - COMPLEX*16 TMP0 - COMPLEX*16 TMP1 - COMPLEX*16 TMP5 - COMPLEX*16 TMP6 - COMPLEX*16 TMP8 - TYPE(ALOHA) V1 - TYPE(ALOHA) V2 - TYPE(ALOHA) V3 - REAL*8 W1 - COMPLEX*16 DENOM - P2(:) = V2 % P (:) - P3(:) = V3 % P (:) - V1%P(:) = +V2%P(:)+V3%P(:) - P1(:) = -V1 % P (:) - TMP0 = (V3 % W(1)*P1(0)-V3 % W(2)*P1(1)-V3 % W(3)*P1(2)-V3 % W(4) - $ *P1(3)) - TMP1 = (V3 % W(1)*P2(0)-V3 % W(2)*P2(1)-V3 % W(3)*P2(2)-V3 % W(4) - $ *P2(3)) - TMP5 = (V2 % W(1)*P1(0)-V2 % W(2)*P1(1)-V2 % W(3)*P1(2)-V2 % W(4) - $ *P1(3)) - TMP6 = (V2 % W(1)*P3(0)-V2 % W(2)*P3(1)-V2 % W(3)*P3(2)-V2 % W(4) - $ *P3(3)) - TMP8 = (V2 % W(1)*V3 % W(1)-V2 % W(2)*V3 % W(2)-V2 % W(3)*V3 % - $ W(3)-V2 % W(4)*V3 % W(4)) - DENOM = COUP/(P1(0)**2-P1(1)**2-P1(2)**2-P1(3)**2 - M1 * (M1 -CI - $ * W1)) - V1%W(1)= DENOM*(TMP8*(-CI*(P2(0))+CI*(P3(0)))+(V2 % W(1)*(-CI - $ *(TMP0)+CI*(TMP1))+V3 % W(1)*(+CI*(TMP5)-CI*(TMP6)))) - V1%W(2)= DENOM*(TMP8*(-CI*(P2(1))+CI*(P3(1)))+(V2 % W(2)*(-CI - $ *(TMP0)+CI*(TMP1))+V3 % W(2)*(+CI*(TMP5)-CI*(TMP6)))) - V1%W(3)= DENOM*(TMP8*(-CI*(P2(2))+CI*(P3(2)))+(V2 % W(3)*(-CI - $ *(TMP0)+CI*(TMP1))+V3 % W(3)*(+CI*(TMP5)-CI*(TMP6)))) - V1%W(4)= DENOM*(TMP8*(-CI*(P2(3))+CI*(P3(3)))+(V2 % W(4)*(-CI - $ *(TMP0)+CI*(TMP1))+V3 % W(4)*(+CI*(TMP5)-CI*(TMP6)))) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/VVV1_0.f b/UNITTEST_proc/Source/DHELAS/VVV1_0.f deleted file mode 100644 index be7989d115..0000000000 --- a/UNITTEST_proc/Source/DHELAS/VVV1_0.f +++ /dev/null @@ -1,53 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C P(3,1)*Metric(1,2) - P(3,2)*Metric(1,2) - P(2,1)*Metric(1,3) + -C P(2,3)*Metric(1,3) + P(1,2)*Metric(2,3) - P(1,3)*Metric(2,3) -C - SUBROUTINE VVV1_0(V1, V2, V3, COUP,VERTEX) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*16 CI - PARAMETER (CI=(0D0,1D0)) - COMPLEX*16 COUP - REAL*8 P1(0:3) - REAL*8 P2(0:3) - REAL*8 P3(0:3) - COMPLEX*16 TMP0 - COMPLEX*16 TMP1 - COMPLEX*16 TMP3 - COMPLEX*16 TMP4 - COMPLEX*16 TMP5 - COMPLEX*16 TMP6 - COMPLEX*16 TMP7 - COMPLEX*16 TMP8 - COMPLEX*16 TMP9 - TYPE(ALOHA) V1 - TYPE(ALOHA) V2 - TYPE(ALOHA) V3 - COMPLEX*16 VERTEX - P1(:) = V1 % P (:) - P2(:) = V2 % P (:) - P3(:) = V3 % P (:) - TMP0 = (V3 % W(1)*P1(0)-V3 % W(2)*P1(1)-V3 % W(3)*P1(2)-V3 % W(4) - $ *P1(3)) - TMP1 = (V3 % W(1)*P2(0)-V3 % W(2)*P2(1)-V3 % W(3)*P2(2)-V3 % W(4) - $ *P2(3)) - TMP3 = (V2 % W(1)*V1 % W(1)-V2 % W(2)*V1 % W(2)-V2 % W(3)*V1 % - $ W(3)-V2 % W(4)*V1 % W(4)) - TMP4 = (V3 % W(1)*V1 % W(1)-V3 % W(2)*V1 % W(2)-V3 % W(3)*V1 % - $ W(3)-V3 % W(4)*V1 % W(4)) - TMP5 = (V2 % W(1)*P1(0)-V2 % W(2)*P1(1)-V2 % W(3)*P1(2)-V2 % W(4) - $ *P1(3)) - TMP6 = (V2 % W(1)*P3(0)-V2 % W(2)*P3(1)-V2 % W(3)*P3(2)-V2 % W(4) - $ *P3(3)) - TMP7 = (P2(0)*V1 % W(1)-P2(1)*V1 % W(2)-P2(2)*V1 % W(3)-P2(3)*V1 - $ % W(4)) - TMP8 = (V2 % W(1)*V3 % W(1)-V2 % W(2)*V3 % W(2)-V2 % W(3)*V3 % - $ W(3)-V2 % W(4)*V3 % W(4)) - TMP9 = (P3(0)*V1 % W(1)-P3(1)*V1 % W(2)-P3(2)*V1 % W(3)-P3(3)*V1 - $ % W(4)) - VERTEX = COUP*(TMP3*(-CI*(TMP0)+CI*(TMP1))+(TMP4*(+CI*(TMP5)-CI - $ *(TMP6))+TMP8*(-CI*(TMP7)+CI*(TMP9)))) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/VVVV1LP0_1.f b/UNITTEST_proc/Source/DHELAS/VVVV1LP0_1.f deleted file mode 100644 index d8ecf01791..0000000000 --- a/UNITTEST_proc/Source/DHELAS/VVVV1LP0_1.f +++ /dev/null @@ -1,30 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C Metric(1,4)*Metric(2,3) - Metric(1,3)*Metric(2,4) -C - SUBROUTINE VVVV1LP0_1(V2, V3, V4, COUP, M1, W1,V1) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*16 CI - PARAMETER (CI=(0D0,1D0)) - COMPLEX*16 COUP - REAL*8 M1 - COMPLEX*16 TMP11 - COMPLEX*16 TMP8 - TYPE(ALOHA) V1 - TYPE(ALOHA) V2 - TYPE(ALOHA) V3 - TYPE(ALOHA) V4 - REAL*8 W1 - V1%P(:) = +V2%P(:)+V3%P(:)+V4%P(:) - TMP11 = (V2 % W(1)*V4 % W(1)-V2 % W(2)*V4 % W(2)-V2 % W(3)*V4 % - $ W(3)-V2 % W(4)*V4 % W(4)) - TMP8 = (V2 % W(1)*V3 % W(1)-V2 % W(2)*V3 % W(2)-V2 % W(3)*V3 % - $ W(3)-V2 % W(4)*V3 % W(4)) - V1%W(1)= COUP*(-CI*(V4 % W(1)*TMP8)+CI*(V3 % W(1)*TMP11)) - V1%W(2)= COUP*(-CI*(V4 % W(2)*TMP8)+CI*(V3 % W(2)*TMP11)) - V1%W(3)= COUP*(-CI*(V4 % W(3)*TMP8)+CI*(V3 % W(3)*TMP11)) - V1%W(4)= COUP*(-CI*(V4 % W(4)*TMP8)+CI*(V3 % W(4)*TMP11)) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/VVVV3LP0_1.f b/UNITTEST_proc/Source/DHELAS/VVVV3LP0_1.f deleted file mode 100644 index da4463779f..0000000000 --- a/UNITTEST_proc/Source/DHELAS/VVVV3LP0_1.f +++ /dev/null @@ -1,30 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C Metric(1,4)*Metric(2,3) - Metric(1,2)*Metric(3,4) -C - SUBROUTINE VVVV3LP0_1(V2, V3, V4, COUP, M1, W1,V1) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*16 CI - PARAMETER (CI=(0D0,1D0)) - COMPLEX*16 COUP - REAL*8 M1 - COMPLEX*16 TMP2 - COMPLEX*16 TMP8 - TYPE(ALOHA) V1 - TYPE(ALOHA) V2 - TYPE(ALOHA) V3 - TYPE(ALOHA) V4 - REAL*8 W1 - V1%P(:) = +V2%P(:)+V3%P(:)+V4%P(:) - TMP2 = (V3 % W(1)*V4 % W(1)-V3 % W(2)*V4 % W(2)-V3 % W(3)*V4 % - $ W(3)-V3 % W(4)*V4 % W(4)) - TMP8 = (V2 % W(1)*V3 % W(1)-V2 % W(2)*V3 % W(2)-V2 % W(3)*V3 % - $ W(3)-V2 % W(4)*V3 % W(4)) - V1%W(1)= COUP*(-CI*(V4 % W(1)*TMP8)+CI*(V2 % W(1)*TMP2)) - V1%W(2)= COUP*(-CI*(V4 % W(2)*TMP8)+CI*(V2 % W(2)*TMP2)) - V1%W(3)= COUP*(-CI*(V4 % W(3)*TMP8)+CI*(V2 % W(3)*TMP2)) - V1%W(4)= COUP*(-CI*(V4 % W(4)*TMP8)+CI*(V2 % W(4)*TMP2)) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/VVVV4LP0_1.f b/UNITTEST_proc/Source/DHELAS/VVVV4LP0_1.f deleted file mode 100644 index f8fcb8d1e8..0000000000 --- a/UNITTEST_proc/Source/DHELAS/VVVV4LP0_1.f +++ /dev/null @@ -1,30 +0,0 @@ -C This File is Automatically generated by ALOHA -C The process calculated in this file is: -C Metric(1,3)*Metric(2,4) - Metric(1,2)*Metric(3,4) -C - SUBROUTINE VVVV4LP0_1(V2, V3, V4, COUP, M1, W1,V1) - USE ALOHA_OBJECT - IMPLICIT NONE - COMPLEX*16 CI - PARAMETER (CI=(0D0,1D0)) - COMPLEX*16 COUP - REAL*8 M1 - COMPLEX*16 TMP11 - COMPLEX*16 TMP2 - TYPE(ALOHA) V1 - TYPE(ALOHA) V2 - TYPE(ALOHA) V3 - TYPE(ALOHA) V4 - REAL*8 W1 - V1%P(:) = +V2%P(:)+V3%P(:)+V4%P(:) - TMP11 = (V2 % W(1)*V4 % W(1)-V2 % W(2)*V4 % W(2)-V2 % W(3)*V4 % - $ W(3)-V2 % W(4)*V4 % W(4)) - TMP2 = (V3 % W(1)*V4 % W(1)-V3 % W(2)*V4 % W(2)-V3 % W(3)*V4 % - $ W(3)-V3 % W(4)*V4 % W(4)) - V1%W(1)= COUP*(-CI*(V3 % W(1)*TMP11)+CI*(V2 % W(1)*TMP2)) - V1%W(2)= COUP*(-CI*(V3 % W(2)*TMP11)+CI*(V2 % W(2)*TMP2)) - V1%W(3)= COUP*(-CI*(V3 % W(3)*TMP11)+CI*(V2 % W(3)*TMP2)) - V1%W(4)= COUP*(-CI*(V3 % W(4)*TMP11)+CI*(V2 % W(4)*TMP2)) - END - - diff --git a/UNITTEST_proc/Source/DHELAS/aloha_file.inc b/UNITTEST_proc/Source/DHELAS/aloha_file.inc deleted file mode 100644 index e62ba70b1b..0000000000 --- a/UNITTEST_proc/Source/DHELAS/aloha_file.inc +++ /dev/null @@ -1 +0,0 @@ -ALOHARoutine = FFV1LP0_3.o FFV1L_1.o FFV1L_2.o FFV1P0_3.o FFV1_0.o FFV1_1.o FFV1_2.o GHGHGL_1.o GHGHGL_2.o MP_FFV1LP0_3.o MP_FFV1L_1.o MP_FFV1L_2.o MP_FFV1P0_3.o MP_FFV1_0.o MP_FFV1_1.o MP_FFV1_2.o MP_GHGHGL_1.o MP_GHGHGL_2.o MP_R2_GG_1_0.o MP_R2_GG_1_R2_GG_2_0.o MP_R2_GG_1_R2_GG_3_0.o MP_R2_GG_2_0.o MP_R2_GG_3_0.o MP_R2_QQ_1_0.o MP_R2_QQ_1_R2_QQ_2_0.o MP_R2_QQ_2_0.o MP_VVV1LP0_1.o MP_VVV1P0_1.o MP_VVV1_0.o MP_VVVV1LP0_1.o MP_VVVV3LP0_1.o MP_VVVV4LP0_1.o R2_GG_1_0.o R2_GG_1_R2_GG_2_0.o R2_GG_1_R2_GG_3_0.o R2_GG_2_0.o R2_GG_3_0.o R2_QQ_1_0.o R2_QQ_1_R2_QQ_2_0.o R2_QQ_2_0.o VVV1LP0_1.o VVV1P0_1.o VVV1_0.o VVVV1LP0_1.o VVVV3LP0_1.o VVVV4LP0_1.o diff --git a/UNITTEST_proc/Source/DHELAS/aloha_functions.f b/UNITTEST_proc/Source/DHELAS/aloha_functions.f deleted file mode 100644 index 8d558bbe0b..0000000000 --- a/UNITTEST_proc/Source/DHELAS/aloha_functions.f +++ /dev/null @@ -1,3084 +0,0 @@ -C############################################################################### -C -C Copyright (c) 2010 The ALOHA Development team and Contributors -C -C This file is a part of the MadGraph5_aMC@NLO project, an application which -C automatically generates Feynman diagrams and matrix elements for arbitrary -C high-energy processes in the Standard Model and beyond. -C -C It is subject to the ALOHA license which should accompany this -C distribution. -C -C############################################################################### - module ALOHA_OBJECT - TYPE ALOHA - SEQUENCE - double complex::W(4) - double complex :: P(0:3) - integer :: flv_index - END TYPE ALOHA - TYPE ALOHA2D - SEQUENCE - double complex::W(16) - double complex :: P(0:3) - integer :: flv_index - END TYPE ALOHA2D - TYPE MP_ALOHA - SEQUENCE - complex*32 :: W(4) - complex*32 :: P(0:3) - integer :: flv_index - END TYPE MP_ALOHA - TYPE MP_ALOHA2D - SEQUENCE - complex*32 :: W(16) - complex*32 :: P(0:3) - integer :: flv_index - END TYPE MP_ALOHA2D - end module ALOHA_OBJECT - - subroutine ixxxxx(p, fmass, nhel, nsf, flavor ,fi) -c -c This subroutine computes a fermion wavefunction with the flowing-IN -c fermion number. -c -c input: -c real p(0:3) : four-momentum of fermion -c real fmass : mass of fermion -c integer nhel = -1 or 1 : helicity of fermion -c integer nsf = -1 or 1 : +1 for particle, -1 for anti-particle -c -c output: -c type(aloha) fi : fermion wavefunction |fi> -c - use ALOHA_OBJECT - implicit none - type(aloha) fi - double complex chi(2) - double precision p(0:3),sf(2),sfomeg(2),omega(2),fmass, - & pp,pp3,sqp0p3,sqm(0:1) - integer nhel,nsf,ip,im,nh,flavor - - double precision rZero, rHalf, rTwo - parameter( rZero = 0.0d0, rHalf = 0.5d0, rTwo = 2.0d0 ) - -c#ifdef HELAS_CHECK -c double precision p2 -c double precision epsi -c parameter( epsi = 2.0d-5 ) -c integer stdo -c parameter( stdo = 6 ) -c#endif -c -c#ifdef HELAS_CHECK -c pp = sqrt(p(1)**2+p(2)**2+p(3)**2) -c if ( abs(p(0))+pp.eq.rZero ) then -c write(stdo,*) -c & ' helas-error : p(0:3) in ixxxxx is zero momentum' -c endif -c if ( p(0).le.rZero ) then -c write(stdo,*) -c & ' helas-error : p(0:3) in ixxxxx has non-positive energy' -c write(stdo,*) -c & ' : p(0) = ',p(0) -c endif -c p2 = (p(0)-pp)*(p(0)+pp) -c if ( abs(p2-fmass**2).gt.p(0)**2*epsi ) then -c write(stdo,*) -c & ' helas-error : p(0:3) in ixxxxx has inappropriate mass' -c write(stdo,*) -c & ' : p**2 = ',p2,' : fmass**2 = ',fmass**2 -c endif -c if (abs(nhel).ne.1) then -c write(stdo,*) ' helas-error : nhel in ixxxxx is not -1,1' -c write(stdo,*) ' : nhel = ',nhel -c endif -c if (abs(nsf).ne.1) then -c write(stdo,*) ' helas-error : nsf in ixxxxx is not -1,1' -c write(stdo,*) ' : nsf = ',nsf -c endif -c#endif - -c Convention for trees -c fi(5) = dcmplx(p(0),p(3))*nsf -c fi(6) = dcmplx(p(1),p(2))*nsf - -c Convention for loop computations - fi%P(0) = p(0)*(-nsf) - fi%P(1) = p(1)*(-nsf) - fi%P(2) = p(2)*(-nsf) - fi%P(3) = p(3)*(-nsf) - fi%flv_index = flavor - - nh = nhel*nsf - - if ( fmass.ne.rZero ) then - - pp = min(p(0),dsqrt(p(1)**2+p(2)**2+p(3)**2)) - - - if ( pp.eq.rZero ) then - - sqm(0) = dsqrt(abs(fmass)) ! possibility of negative fermion masses - sqm(1) = sign(sqm(0),fmass) ! possibility of negative fermion masses - ip = (1+nh)/2 - im = (1-nh)/2 - - fi%W(1) = ip * sqm(ip) - fi%W(2) = im*nsf * sqm(ip) - fi%W(3) = ip*nsf * sqm(im) - fi%W(4) = im * sqm(im) - - else - - sf(1) = dble(1+nsf+(1-nsf)*nh)*rHalf - sf(2) = dble(1+nsf-(1-nsf)*nh)*rHalf - omega(1) = dsqrt(p(0)+pp) - omega(2) = fmass/omega(1) - ip = (3+nh)/2 - im = (3-nh)/2 - sfomeg(1) = sf(1)*omega(ip) - sfomeg(2) = sf(2)*omega(im) - pp3 = max(pp+p(3),rZero) - chi(1) = dcmplx( dsqrt(pp3*rHalf/pp) ) - if ( pp3.eq.rZero ) then - chi(2) = dcmplx(-nh ) - else - chi(2) = dcmplx( nh*p(1) , p(2) )/dsqrt(rTwo*pp*pp3) - endif - - fi%W(1) = sfomeg(1)*chi(im) - fi%W(2) = sfomeg(1)*chi(ip) - fi%W(3) = sfomeg(2)*chi(im) - fi%W(4) = sfomeg(2)*chi(ip) - - endif - - else - - if(p(1).eq.0d0.and.p(2).eq.0d0.and.p(3).lt.0d0) then - sqp0p3 = 0d0 - else - sqp0p3 = dsqrt(max(p(0)+p(3),rZero))*nsf - end if - chi(1) = dcmplx( sqp0p3 ) - if ( sqp0p3.eq.rZero ) then - chi(2) = dcmplx(-nhel )*dsqrt(rTwo*p(0)) - else - chi(2) = dcmplx( nh*p(1), p(2) )/sqp0p3 - endif - if ( nh.eq.1 ) then - fi%W(1) = dcmplx( rZero ) - fi%W(2) = dcmplx( rZero ) - fi%W(3) = chi(1) - fi%W(4) = chi(2) - else - fi%W(1) = chi(2) - fi%W(2) = chi(1) - fi%W(3) = dcmplx( rZero ) - fi%W(4) = dcmplx( rZero ) - endif - endif -c - return - end - - - subroutine ixxxso(p, fmass, nhel, nsf, flavor ,fi) -c -c This subroutine computes a fermion wavefunction with the flowing-IN -c fermion number. -c -c input: -c real p(0:3) : four-momentum of fermion -c real fmass : mass of fermion -c integer nhel = -1 or 1 : helicity of fermion -c integer nsf = -1 or 1 : +1 for particle, -1 for anti-particle -c -c output: -c type(aloha) fi : fermion wavefunction |fi> -c - use ALOHA_OBJECT - implicit none - type(aloha) fi - double complex chi(2) - double precision p(0:3),sf(2),sfomeg(2),omega(2),fmass, - & pp,pp3,sqp0p3,sqm(0:1) - integer nhel,nsf,ip,im,nh,flavor - - double precision rZero, rHalf, rTwo - parameter( rZero = 0.0d0, rHalf = 0.5d0, rTwo = 2.0d0 ) - -c#ifdef HELAS_CHECK -c double precision p2 -c double precision epsi -c parameter( epsi = 2.0d-5 ) -c integer stdo -c parameter( stdo = 6 ) -c#endif -c -c#ifdef HELAS_CHECK -c pp = sqrt(p(1)**2+p(2)**2+p(3)**2) -c if ( abs(p(0))+pp.eq.rZero ) then -c write(stdo,*) -c & ' helas-error : p(0:3) in ixxxxx is zero momentum' -c endif -c if ( p(0).le.rZero ) then -c write(stdo,*) -c & ' helas-error : p(0:3) in ixxxxx has non-positive energy' -c write(stdo,*) -c & ' : p(0) = ',p(0) -c endif -c p2 = (p(0)-pp)*(p(0)+pp) -c if ( abs(p2-fmass**2).gt.p(0)**2*epsi ) then -c write(stdo,*) -c & ' helas-error : p(0:3) in ixxxxx has inappropriate mass' -c write(stdo,*) -c & ' : p**2 = ',p2,' : fmass**2 = ',fmass**2 -c endif -c if (abs(nhel).ne.1) then -c write(stdo,*) ' helas-error : nhel in ixxxxx is not -1,1' -c write(stdo,*) ' : nhel = ',nhel -c endif -c if (abs(nsf).ne.1) then -c write(stdo,*) ' helas-error : nsf in ixxxxx is not -1,1' -c write(stdo,*) ' : nsf = ',nsf -c endif -c#endif - -c Convention for trees -c fi(5) = dcmplx(p(0),p(3))*nsf -c fi(6) = dcmplx(p(1),p(2))*nsf - -c$$$c Convention for loop computations -c$$$ fi(1) = dcmplx(p(0),0.D0)*(-nsf) -c$$$ fi(2) = dcmplx(p(1),0.D0)*(-nsf) -c$$$ fi(3) = dcmplx(p(2),0.D0)*(-nsf) -c$$$ fi(4) = dcmplx(p(3),0.D0)*(-nsf) - - fi%P(0) = p(0)*(-nsf) - fi%P(1) = p(1)*(-nsf) - fi%P(2) = p(2)*(-nsf) - fi%P(3) = p(3)*(-nsf) - fi%flv_index = flavor - - nh = nhel*nsf - - if ( fmass.ne.rZero ) then - - pp = min(p(0),dsqrt(p(1)**2+p(2)**2+p(3)**2)) - - if ( pp.eq.rZero ) then - - sqm(0) = dsqrt(abs(fmass)) ! possibility of negative fermion masses - sqm(1) = sign(sqm(0),fmass) ! possibility of negative fermion masses - ip = (1+nh)/2 - im = (1-nh)/2 - - fi%W(1) = ip * sqm(ip) - fi%W(2) = im*nsf * sqm(ip) - fi%W(3) = ip*nsf * sqm(im) - fi%W(4) = im * sqm(im) - - else - - sf(1) = dble(1+nsf+(1-nsf)*nh)*rHalf - sf(2) = dble(1+nsf-(1-nsf)*nh)*rHalf - omega(1) = dsqrt(p(0)+pp) - omega(2) = fmass/omega(1) - ip = (3+nh)/2 - im = (3-nh)/2 - sfomeg(1) = sf(1)*omega(ip) - sfomeg(2) = sf(2)*omega(im) - pp3 = max(pp+p(3),rZero) - chi(1) = dcmplx( dsqrt(pp3*rHalf/pp) ) - if ( pp3.eq.rZero ) then - chi(2) = dcmplx(-nh ) - else - chi(2) = dcmplx( nh*p(1) , p(2) )/dsqrt(rTwo*pp*pp3) - endif - - fi%W(1) = sfomeg(1)*chi(im) - fi%W(2) = sfomeg(1)*chi(ip) - fi%W(3) = sfomeg(2)*chi(im) - fi%W(4) = sfomeg(2)*chi(ip) - - endif - - else - - if(p(1).eq.0d0.and.p(2).eq.0d0.and.p(3).lt.0d0) then - sqp0p3 = 0d0 - else - sqp0p3 = dsqrt(max(p(0)+p(3),rZero))*nsf - end if - chi(1) = dcmplx( sqp0p3 ) - if ( sqp0p3.eq.rZero ) then - chi(2) = dcmplx(-nhel )*dsqrt(rTwo*p(0)) - else - chi(2) = dcmplx( nh*p(1), p(2) )/sqp0p3 - endif - if ( nh.eq.1 ) then - fi%W(1) = dcmplx( rZero ) - fi%W(2) = dcmplx( rZero ) - fi%W(3) = chi(1) - fi%W(4) = chi(2) - else - fi%W(1) = chi(2) - fi%W(2) = chi(1) - fi%W(3) = dcmplx( rZero ) - fi%W(4) = dcmplx( rZero ) - endif - endif -c - return - end - - - subroutine mp_ixxxxx(p, fmass, nhel, nsf, flavor ,fi) -c -c This subroutine computes a fermion wavefunction with the flowing-IN -c fermion number, in QUADRUPLE PRECISIOn -c -c input: -c real p(0:3) : four-momentum of fermion -c real fmass : mass of fermion -c integer nhel = -1 or 1 : helicity of fermion -c integer nsf = -1 or 1 : +1 for particle, -1 for anti-particle -c -c output: -c type(mp_aloha) fi : fermion wavefunction |fi> -c - use ALOHA_OBJECT - implicit none - type(mp_aloha) fi - complex*32 chi(2) - real*16 p(0:3),sf(2),sfomeg(2),omega(2),fmass, - & pp,pp3,sqp0p3,sqm(0:1) - integer nhel,nsf,ip,im,nh,flavor - - real*16 rZero, rHalf, rTwo - parameter( rZero = 0.0e0_16, rHalf = 0.5e0_16, rTwo = 2.0e0_16 ) -c Convention for loop computations - fi%P(0) = p(0)*(-nsf) - fi%P(1) = p(1)*(-nsf) - fi%P(2) = p(2)*(-nsf) - fi%P(3) = p(3)*(-nsf) - fi%flv_index = flavor - - nh = nhel*nsf - - if ( fmass.ne.rZero ) then - - pp = min(p(0),sqrt(p(1)**2+p(2)**2+p(3)**2)) - - if ( pp.eq.rZero ) then - - sqm(0) = sqrt(abs(fmass)) ! possibility of negative fermion masses - sqm(1) = sign(sqm(0),fmass) ! possibility of negative fermion masses - ip = (1+nh)/2 - im = (1-nh)/2 - - fi%W(1) = ip * sqm(ip) - fi%W(2) = im*nsf * sqm(ip) - fi%W(3) = ip*nsf * sqm(im) - fi%W(4) = im * sqm(im) - - else - - sf(1) = REAL(1+nsf+(1-nsf)*nh,KIND=16)*rHalf - sf(2) = REAL(1+nsf-(1-nsf)*nh,KIND=16)*rHalf - omega(1) = sqrt(p(0)+pp) - omega(2) = fmass/omega(1) - ip = (3+nh)/2 - im = (3-nh)/2 - sfomeg(1) = sf(1)*omega(ip) - sfomeg(2) = sf(2)*omega(im) - pp3 = max(pp+p(3),rZero) - chi(1) = cmplx( sqrt(pp3*rHalf/pp), KIND=16 ) - if ( pp3.eq.rZero ) then - chi(2) = cmplx(-nh ,KIND=16) - else - chi(2) = cmplx( nh*p(1) , p(2),KIND=16)/sqrt(rTwo*pp*pp3) - endif - - fi%W(1) = sfomeg(1)*chi(im) - fi%W(2) = sfomeg(1)*chi(ip) - fi%W(3) = sfomeg(2)*chi(im) - fi%W(4) = sfomeg(2)*chi(ip) - - endif - - else - - if(p(1).eq.0d0.and.p(2).eq.0d0.and.p(3).lt.0d0) then - sqp0p3 = 0d0 - else - sqp0p3 = sqrt(max(p(0)+p(3),rZero))*nsf - end if - chi(1) = cmplx( sqp0p3 ,KIND=16) - if ( sqp0p3.eq.rZero ) then - chi(2) = cmplx(-nhel ,KIND=16)*sqrt(rTwo*p(0)) - else - chi(2) = cmplx( nh*p(1), p(2) ,KIND=16)/sqp0p3 - endif - if ( nh.eq.1 ) then - fi%W(1) = cmplx( rZero ,KIND=16) - fi%W(2) = cmplx( rZero ,KIND=16) - fi%W(3) = chi(1) - fi%W(4) = chi(2) - else - fi%W(1) = chi(2) - fi%W(2) = chi(1) - fi%W(3) = cmplx( rZero ,KIND=16) - fi%W(4) = cmplx( rZero ,KIND=16) - endif - endif -c - return - end - - subroutine oxxxxx(p,fmass,nhel,nsf, flavor , fo) -c -c This subroutine computes a fermion wavefunction with the flowing-OUT -c fermion number. -c -c input: -c real p(0:3) : four-momentum of fermion -c real fmass : mass of fermion -c integer nhel = -1 or 1 : helicity of fermion -c integer nsf = -1 or 1 : +1 for particle, -1 for anti-particle -c -c output: -c type(aloha) fo : fermion wavefunction -c Note: There are 4 components for the spinor and four for the -c momentum. - implicit none - double complex fi(8),chi(2), fmass -c double precision p(0:3),sf(2),sfomeg(2),omega(2),fmass, -c & pp,pp3,sqp0p3,sqm(0:1) - double complex sqm(0:1) - double precision sf(2),ffmass - double complex p(0:3), sfomeg(2),omega(2), - & pp,pp3,sqp0p3 - integer nhel,nsf,ip,im,nh - - double precision rZero, rHalf, rTwo - parameter( rZero = 0.0d0, rHalf = 0.5d0, rTwo = 2.0d0 ) - - - -c fi(5) = dcmplx(p(0),p(3))*nsf -c fi(6) = dcmplx(p(1),p(2))*nsf - fi(5) = p(0)*nsf - fi(6) = p(1)*nsf - fi(7) = p(2)*nsf - fi(8) = p(3)*nsf - - nh = nhel*nsf - - fmass = sqrt(p(0)**2-p(1)**2-p(2)**2-p(3)**2) - - if ( ffmass.ne.rZero ) then -c special treatment for massless particles. -c pp = min(p(0),sqrt(p(1)**2+p(2)**2+p(3)**2)) - pp=sqrt(p(1)**2+p(2)**2+p(3)**2) -c for time-like four-momenta we can always think of it as the p_vec^2 - if ( abs(pp).eq.rZero ) then -c particle at rest. - sqm(0) = sqrt(fmass) ! possibility of negative fermion masses - sqm(1) = sqm(0) ! possibility of negative fermion masses - ip = (1+nh)/2 - im = (1-nh)/2 - - fi(1) = ip * sqm(ip) - fi(2) = im*nsf * sqm(ip) - fi(3) = ip*nsf * sqm(im) - fi(4) = im * sqm(im) - - else -c standard spinor - - pp=sqrt(p(1)**2+p(2)**2+p(3)**2) - write(*,*) 'ppre=',pp -c if( (dble(p(0)) .lt. 0 .and. dble(pp) .gt. 0) .or. -c & (dble(p(0)) .lt. 0 .and. dble(pp) .gt. 0) ) then -c pp=-pp -c endif - sf(1) = dble(1+nsf+(1-nsf)*nh)*rHalf -c fermion spin using HELAS conventions. - sf(2) = dble(1+nsf-(1-nsf)*nh)*rHalf - omega(1) = sqrt(p(0)+pp) -c the omega of the definition. -c omega(2) = fmass/omega(1) - omega(2) = sqrt(p(0)-pp) -c the prefactor - ip = (3+nh)/2 - im = (3-nh)/2 - sfomeg(1) = sf(1)*omega(ip) - sfomeg(2) = sf(2)*omega(im) -c pp3 = max(pp+p(3),rZero) - pp3=pp+p(3) - chi(1) = sqrt(pp3*rHalf/pp) - if ( abs(pp3).eq.rZero ) then - chi(2) = dcmplx(-nh ) - else - chi(2) = ( (nh*p(1)) + ((0d0,1d0)*p(2)) )/ - .sqrt(rTwo*pp*pp3) - endif - - -c Write(*,*) 'Chi=',Chi(1),' and ',Chi(2) - - fi(1) = sfomeg(1)*chi(im) - fi(2) = sfomeg(1)*chi(ip) -c Write(*,*) 'fi(2)=',fi(2) - fi(3) = sfomeg(2)*chi(im) -c Write(*,*) 'fi(3)=',fi(3) - fi(4) = sfomeg(2)*chi(ip) - - endif - - else - -c if(zabs(p(1)).eq.0d0.and.zabs(p(2)).eq.0d0.and. -c .zabs(p(3)).lt.0d0) then -c sqp0p3 = 0d0 -c else - sqp0p3 = sqrt(p(0)+p(3))*nsf -c end if - chi(1) = sqp0p3 - if ( abs(sqp0p3).eq.rZero ) then - chi(2) = dcmplx(-nhel )*sqrt(rTwo*p(0)) - else - chi(2) = ( nh*p(1) + ((0d0,1d0)*p(2) ) )/sqp0p3 - endif - if ( nh.eq.1 ) then - fi(1) = dcmplx( rZero ) - fi(2) = dcmplx( rZero ) - fi(3) = chi(1) - fi(4) = chi(2) - else - fi(1) = chi(2) - fi(2) = chi(1) - fi(3) = dcmplx( rZero ) - fi(4) = dcmplx( rZero ) - endif - endif - - return - end - - subroutine olxxxx(p,ffmass,nhel,nsf,fo) -c -c This subroutine computes a fermion wavefunction with the flowing-OUT -c fermion number and defined with complex ONSHELL momentum. -c -c input: -c complex p(0:3) : four-momentum of fermion -c real fmass : mass of fermion -c integer nhel = -1 or 1 : helicity of fermion -c integer nsf = -1 or 1 : +1 for particle, -1 for anti-particle -c -c output: -c complex fo(8) : fermion wavefunction islatin=true if letter is a latin letter -c ++ -c +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - - subroutine LHA_islatin(letter,islatin) - implicit none - - logical islatin - character letter - integer i - - islatin=.false. - i=ichar(letter) - if(i.ge.65.and.i.le. 90) islatin=.true. - if(i.ge.97.and.i.le.122) islatin=.true. - - end - -c +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -c ++ -c ++ LHA_isnum -> isnum=true if letter is a number -c ++ -c +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - - subroutine LHA_isnum(letter,isnum) - implicit none - - logical isnum - character letter - character*10 ref - integer i - - isnum=.false. - ref='1234567890' - - do i=1,10 - if(letter .eq. ref(i:i)) isnum=.true. - end do - - end - -c +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -c ++ -c ++ LHA_firststring -> first is the first "word" of string -c ++ Warning: string is returned with first REMOVED! -c ++ -c +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - - subroutine LHA_firststring(first,string) - - implicit none - character*(*) string - character*(*) first - - if(len_trim(string).le.0) return - - do while(string(1:1) .eq. ' ') - string=string(2:len(string)) - end do - if (index(string,' ').gt.1) then - first=string(1:index(string,' ')-1) - string=string(index(string,' '):len(string)) - else - first=string - end if - - end - - - subroutine LHA_case_trap(name) -c +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -c ++ -c ++ LHA_case_trap -> change string to lower case -c ++ -c +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - implicit none - - character*20 name - integer i,k - - do i=1,20 - k=ichar(name(i:i)) - if(k.ge.65.and.k.le.90) then !upper case A-Z - k=ichar(name(i:i))+32 - name(i:i)=char(k) - endif - enddo - - return - end - -c +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -c ++ -c ++ LHA_blockread -> read a LHA line and return parameter name (evntually found in -c ++ a ref file) and value -c ++ -c +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - - subroutine LHA_blockread(blockname,buff,par,val,found) - - implicit none - character*132 buff,buffer,curr_ref,curr_buff - character*20 blockname,val,par,temp,first_ref,first_line - logical fopened - integer ref_file - logical islast,isnum,found - character*20 temp_val - - logical isBlank - integer i - character(512) IdentCardPath - - character(512) ParamCardPath - data ParamCardPath/'.'/ - common/ParamCardPath/ParamCardPath - -c ********************************************************************* -c Try to find a correspondance in ident_card -c - - IdentCardPath='' - i =1 - isBlank = .False. - do while (i.le.LEN(ParamCardPath) .and. - \ .not. isBlank) - if (ParamCardPath(i:i).eq.' ') then - isBlank=.True. - else - i=i+1 - endif - enddo - IdentCardPath = ParamCardPath(1:i-1)//'/ident_card.dat' - ref_file = 20 - call LHA_open_file(ref_file,IdentCardPath,fopened) - if(.not. fopened) goto 99 ! If the file does not exist -> no matter, use default! - - islast=.false. - found=.false. - do while(.not. found)!run over reference file - - - ! read a line - read(ref_file,'(a132)',end=98,err=98) buffer - - ! Seek a corresponding blockname - call LHA_firststring(temp,buffer) - call LHA_case_trap(temp) - - if(temp .eq. blockname) then - ! Seek for a corresponding LHA code - curr_ref=buffer - curr_buff=buff - first_ref='' - first_line='' - - do while((.not. islast).and.(first_ref .eq. first_line)) - call LHA_firststring(first_ref,curr_ref) - call LHA_firststring(first_line,curr_buff) - call LHA_islatin(first_ref(1:1),islast) - if (islast) then - par=first_ref - val=first_line ! If found set param name & value - found=.true. - end if - end do - end if - - end do -98 close(ref_file) -99 return - end - - -c +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -c ++ -c ++ LHA_loadcard -> Open a LHA file and load all model param in a table -c ++ -c +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - - subroutine LHA_loadcard(param_name,npara,param,value) - - implicit none - - integer maxpara - parameter (maxpara=1000) - character*20 param(maxpara),value(maxpara),val,par - character*20 blockname - integer npara - logical fopened,found - integer iunit,GL,logfile - character*20 ctemp - character*132 buff - character*20 tag - character*132 temp - character*(*) param_name - data iunit/21/ - data logfile/22/ - - logical WriteParamLog - common/IOcontrol/WriteParamLog - - GL=0 - npara=1 - - param(1)=' ' - value(1)=' ' - - ! Try to open param-card file - call LHA_open_file(iunit,param_name,fopened) - if(.not.fopened) then - write(*,*) 'Error: Could not open file',param_name - write(*,*) 'Exiting' - stop - endif - - ! Try to open log file - if (WriteParamLog) then - open (unit = logfile, file = "param.log") - endif - - ! Scan the data file - do while(.true.) - - read(iunit,'(a132)',end=99,err=99) buff - - if(buff .ne. '' .and. buff(1:1) .ne.'#') then ! Skip comments and empty lines - - tag=buff(1:5) - call LHA_case_trap(tag) ! Select decay/block tag - if(tag .eq. 'block') then ! If we are in a block, get the blockname - temp=buff(7:132) - call LHA_firststring(blockname,temp) - call LHA_case_trap(blockname) - else if (tag .eq. 'decay') then ! If we are in a decay, directly try to get back the correct name/value pair - blockname='decay' - temp=buff(7:132) - call LHA_blockread(blockname,temp,par,val,found) - if(found) GL=1 - else if ((tag .eq. 'qnumbers').or.(blockname.eq.'')) then! if qnumbers or empty tag do nothing - blockname='' - else ! If we are in valid block, try to get back a name/value pair - call LHA_blockread(blockname,buff,par,val,found) - if(found) GL=1 - end if - - !if LHA_blockread has been called, record name and value - - if(GL .eq. 1) then - value(npara)=val - ctemp=par - call LHA_case_trap(ctemp) - param(npara)=ctemp - npara=npara+1 - GL=0 - if (WriteParamLog) then - write (logfile,*) 'Parameter ',ctemp, - & ' has been read with value ',val - endif - endif - - endif - enddo - - npara=npara-1 - 99 close(iunit) - if (WriteParamLog) then - close(logfile) - endif - - return - - end - - - - subroutine LHA_get_real_silent(npara,param,value,name,var,def_value_num) -c---------------------------------------------------------------------------------- -c finds the parameter named "name" in param and associate to "value" in value -c---------------------------------------------------------------------------------- - implicit none - -c -c parameters -c - integer maxpara - parameter (maxpara=1000) -c -c arguments -c - integer npara - character*20 param(maxpara),value(maxpara) - character*(*) name - real*8 var,def_value_num - character*20 c_param,c_name,ctemp - character*19 def_value -c -c local -c - logical found, log - integer i -c -c start -c - log = .false. - goto 10 - - entry LHA_get_real(npara,param,value,name,var,def_value_num) - log = .true. - - 10 i=1 - found=.false. - do while(.not.found.and.i.le.npara) - ctemp=param(i) - call LHA_firststring(c_param,ctemp) - ctemp=name - call LHA_firststring(c_name,ctemp) - call LHA_case_trap(c_name) - call LHA_case_trap(c_param) - found = (c_param .eq. c_name) - if (found) then - read(value(i),*) var - end if - i=i+1 - enddo - if (.not.found) then - if (log) then - write (*,*) "Warning: parameter ",name," not found" - write (*,*) " setting it to default value ", - & def_value_num - endif - var=def_value_num - endif - return - - end -c - - - subroutine MP_LHA_get_real_silent(npara,param,value,name,var, - &def_value_num) -c---------------------------------------------------------------------------------- -c finds the parameter named "name" in param and associate to "value" in value -c---------------------------------------------------------------------------------- - implicit none - -c -c parameters -c - integer maxpara - parameter (maxpara=1000) -c -c arguments -c - integer npara - character*20 param(maxpara),value(maxpara) - character*(*) name - real*16 var,def_value_num - real*8 buff - character*20 c_param,c_name,ctemp - character*19 def_value -c -c local -c - logical found, log - integer i -c -c start -c - log = .false. - goto 10 - entry MP_LHA_get_real(npara,param,value,name,var, - & def_value_num) - log = .true. - - 10 i=1 - found=.false. - do while(.not.found.and.i.le.npara) - ctemp=param(i) - call LHA_firststring(c_param,ctemp) - ctemp=name - call LHA_firststring(c_name,ctemp) - call LHA_case_trap(c_name) - call LHA_case_trap(c_param) - found = (c_param .eq. c_name) - if (found) then - read(value(i),*) buff - var=buff - end if - i=i+1 - enddo - if (.not.found) then - if (log) then - buff = def_value_num - write (*,*) "Warning: parameter ",name," not found" - write (*,*) " setting it to default value ", - & buff - endif - var=def_value_num - endif - return - - end -c - - - - subroutine LHA_open_file(lun,filename,fopened) -c*********************************************************************** -c opens file input-card.dat in current directory or above -c*********************************************************************** - implicit none -c -c Arguments -c - integer lun - logical fopened - character*(*) filename - character*512 tempname - integer fine - integer dirup,i - - character(512) ParamCardPath - common/ParamCardPath/ParamCardPath - -c----- -c Begin Code -c----- -c -c first check that we will end in the main directory -c - ! Somehow it seems important to make sure the flow is - ! iunit is closed before opening it. - close(lun) - open(unit=lun,file=filename,status='old',ERR=20) -c write(*,*) 'read model file ',filename - fopened=.true. - if (filename(len(trim(filename))-13:len(trim(filename))).eq."param_card.dat") then - ParamCardPath = filename(1:len(trim(filename))-15) - endif - return - -20 tempname=filename - fine=index(tempname,' ') - if(fine.eq.0) fine=len(tempname) - tempname=tempname(1:fine) -c -c if I have to read a card -c - if(index(filename,"_card").gt.0) then - tempname='./Cards/'//tempname - endif - - fopened=.false. - do i=0,5 - open(unit=lun,file=tempname,status='old',ERR=30) - fopened=.true. -c write(*,*) 'read model file ',tempname - exit -30 tempname='../'//tempname - if (i.eq.5)then - write(*,*) 'Warning: file ',filename, - & ' not found in the parent directories!(not found for mp_)' - stop - endif - enddo - - return - end - diff --git a/UNITTEST_proc/Source/MODEL/makefile b/UNITTEST_proc/Source/MODEL/makefile deleted file mode 100644 index 1275410de2..0000000000 --- a/UNITTEST_proc/Source/MODEL/makefile +++ /dev/null @@ -1,56 +0,0 @@ -# ---------------------------------------------------------------------------- -# -# Makefile for model library -# -# ---------------------------------------------------------------------------- - -# Check for ../make_opts -ifeq ($(wildcard ../make_opts), ../make_opts) - include ../make_opts - FFLAGS+= -fPIC -else - FFLAGS+= -fPIC -ffixed-line-length-132 - FC=gfortran -endif - -include makeinc.inc - -LIBDIR=../../lib/ -LIBRARY=libmodel.$(libext) -LIBRARY_SHARED=libmodel.$(dylibext) - -all: $(LIBDIR)$(LIBRARY) - -helas_couplings: helas_couplings.o $(LIBRARY) - $(FC) $(FFLAGS) -o $@ $^ - -testprog: testprog.o $(LIBRARY) - $(FC) $(FFLAGS) -o $@ $^ - -$(LIBRARY): $(MODEL) - ar cru $(LIBRARY) $(MODEL) - ranlib $(LIBRARY) - -$(LIBDIR)$(LIBRARY): $(MODEL) - $(call CREATELIB, $@, $^) - -$(LIBDIR)$(LIBRARY_SHARED): $(MODEL) - $(FC) -shared -o $@ $^ $(LDFLAGS) - -shared: $(LIBDIR)$(LIBRARY_SHARED) -clean: - $(RM) *.o $(LIBDIR)$(LIBRARY) - -couplings.o: ../maxparticles.inc ../run.inc ../cuts.inc - -../maxparticles.inc: - touch ../maxparticles.inc - -../run.inc: - touch ../run.inc - -../cuts.inc: - echo " logical fixed_extra_scale" > ../cuts.inc - echo " integer maxjetflavor" >> ../cuts.inc - echo " double precision mue_ref_fixed, mue_over_ref" >> ../cuts.inc - diff --git a/UNITTEST_proc/Source/MODEL/makeinc.inc b/UNITTEST_proc/Source/MODEL/makeinc.inc deleted file mode 100644 index 699348c3ac..0000000000 --- a/UNITTEST_proc/Source/MODEL/makeinc.inc +++ /dev/null @@ -1,5 +0,0 @@ -############################################################################# -# written by the UFO converter -############################################################################# - -MODEL = flavor_couplings.o couplings.o lha_read.o printout.o rw_para.o model_functions.o get_color.o couplings1.o couplings2.o couplings3.o mp_couplings1.o mp_couplings2.o mp_couplings3.o \ No newline at end of file diff --git a/UNITTEST_proc/Source/MODEL/model_functions.f b/UNITTEST_proc/Source/MODEL/model_functions.f deleted file mode 100644 index 0a5f1443ac..0000000000 --- a/UNITTEST_proc/Source/MODEL/model_functions.f +++ /dev/null @@ -1,1038 +0,0 @@ -ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c written by the UFO converter -ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc - - DOUBLE COMPLEX FUNCTION COND(CONDITION,TRUECASE,FALSECASE) - IMPLICIT NONE - DOUBLE COMPLEX CONDITION,TRUECASE,FALSECASE - IF(CONDITION.EQ.(0.0D0,0.0D0)) THEN - COND=TRUECASE - ELSE - COND=FALSECASE - ENDIF - END - - DOUBLE COMPLEX FUNCTION CONDIF(CONDITION,TRUECASE,FALSECASE) - IMPLICIT NONE - LOGICAL CONDITION - DOUBLE COMPLEX TRUECASE,FALSECASE - IF(CONDITION) THEN - CONDIF=TRUECASE - ELSE - CONDIF=FALSECASE - ENDIF - END - - DOUBLE COMPLEX FUNCTION RECMS(CONDITION,EXPR) - IMPLICIT NONE - LOGICAL CONDITION - DOUBLE COMPLEX EXPR - IF(CONDITION)THEN - RECMS=EXPR - ELSE - RECMS=DCMPLX(DBLE(EXPR)) - ENDIF - END - - DOUBLE COMPLEX FUNCTION REGLOG(ARG_IN) - IMPLICIT NONE - DOUBLE COMPLEX TWOPII - PARAMETER (TWOPII=2.0D0*3.1415926535897932D0*(0.0D0,1.0D0)) - DOUBLE COMPLEX ARG_IN - DOUBLE COMPLEX ARG - ARG=ARG_IN - IF(DABS(DIMAG(ARG)).EQ.0.0D0)THEN - ARG=DCMPLX(DBLE(ARG),0.0D0) - ENDIF - IF(DABS(DBLE(ARG)).EQ.0.0D0)THEN - ARG=DCMPLX(0.0D0,DIMAG(ARG)) - ENDIF - IF(ARG.EQ.(0.0D0,0.0D0)) THEN - REGLOG=(0.0D0,0.0D0) - ELSE - REGLOG=LOG(ARG) - ENDIF - END - - DOUBLE COMPLEX FUNCTION REGLOGP(ARG_IN) - IMPLICIT NONE - DOUBLE COMPLEX TWOPII - PARAMETER (TWOPII=2.0D0*3.1415926535897932D0*(0.0D0,1.0D0)) - DOUBLE COMPLEX ARG_IN - DOUBLE COMPLEX ARG - ARG=ARG_IN - IF(DABS(DIMAG(ARG)).EQ.0.0D0)THEN - ARG=DCMPLX(DBLE(ARG),0.0D0) - ENDIF - IF(DABS(DBLE(ARG)).EQ.0.0D0)THEN - ARG=DCMPLX(0.0D0,DIMAG(ARG)) - ENDIF - IF(ARG.EQ.(0.0D0,0.0D0))THEN - REGLOGP=(0.0D0,0.0D0) - ELSE - IF(DBLE(ARG).LT.0.0D0.AND.DIMAG(ARG).LT.0.0D0)THEN - REGLOGP=LOG(ARG) + TWOPII - ELSE - REGLOGP=LOG(ARG) - ENDIF - ENDIF - END - - DOUBLE COMPLEX FUNCTION REGLOGM(ARG_IN) - IMPLICIT NONE - DOUBLE COMPLEX TWOPII - PARAMETER (TWOPII=2.0D0*3.1415926535897932D0*(0.0D0,1.0D0)) - DOUBLE COMPLEX ARG_IN - DOUBLE COMPLEX ARG - ARG=ARG_IN - IF(DABS(DIMAG(ARG)).EQ.0.0D0)THEN - ARG=DCMPLX(DBLE(ARG),0.0D0) - ENDIF - IF(DABS(DBLE(ARG)).EQ.0.0D0)THEN - ARG=DCMPLX(0.0D0,DIMAG(ARG)) - ENDIF - IF(ARG.EQ.(0.0D0,0.0D0))THEN - REGLOGM=(0.0D0,0.0D0) - ELSE - IF(DBLE(ARG).LT.0.0D0.AND.DIMAG(ARG).GT.0.0D0)THEN - REGLOGM=LOG(ARG) - TWOPII - ELSE - REGLOGM=LOG(ARG) - ENDIF - ENDIF - END - - DOUBLE COMPLEX FUNCTION REGSQRT(ARG_IN) - IMPLICIT NONE - DOUBLE COMPLEX ARG_IN - DOUBLE COMPLEX ARG - ARG=ARG_IN - IF(DABS(DIMAG(ARG)).EQ.0.0D0)THEN - ARG=DCMPLX(DBLE(ARG),0.0D0) - ENDIF - IF(DABS(DBLE(ARG)).EQ.0.0D0)THEN - ARG=DCMPLX(0.0D0,DIMAG(ARG)) - ENDIF - REGSQRT=SQRT(ARG) - END - - DOUBLE COMPLEX FUNCTION GRREGLOG(LOGSW,EXPR1_IN,EXPR2_IN) - IMPLICIT NONE - DOUBLE COMPLEX TWOPII - PARAMETER (TWOPII=2.0D0*3.1415926535897932D0*(0.0D0,1.0D0)) - DOUBLE COMPLEX EXPR1_IN,EXPR2_IN - DOUBLE COMPLEX EXPR1,EXPR2 - DOUBLE PRECISION LOGSW - DOUBLE PRECISION IMAGEXPR - LOGICAL FIRSTSHEET - EXPR1=EXPR1_IN - EXPR2=EXPR2_IN - IF(DABS(DIMAG(EXPR1)).EQ.0.0D0)THEN - EXPR1=DCMPLX(DBLE(EXPR1),0.0D0) - ENDIF - IF(DABS(DBLE(EXPR1)).EQ.0.0D0)THEN - EXPR1=DCMPLX(0.0D0,DIMAG(EXPR1)) - ENDIF - IF(DABS(DIMAG(EXPR2)).EQ.0.0D0)THEN - EXPR2=DCMPLX(DBLE(EXPR2),0.0D0) - ENDIF - IF(DABS(DBLE(EXPR2)).EQ.0.0D0)THEN - EXPR2=DCMPLX(0.0D0,DIMAG(EXPR2)) - ENDIF - IF(EXPR1.EQ.(0.0D0,0.0D0))THEN - GRREGLOG=(0.0D0,0.0D0) - ELSE - IMAGEXPR=DIMAG(EXPR1)*DIMAG(EXPR2) - FIRSTSHEET=IMAGEXPR.GE.0.0D0 - FIRSTSHEET=FIRSTSHEET.OR.DBLE(EXPR1).GE.0.0D0 - FIRSTSHEET=FIRSTSHEET.OR.DBLE(EXPR2).GE.0.0D0 - IF(FIRSTSHEET)THEN - GRREGLOG=LOG(EXPR1) - ELSE - IF(DIMAG(EXPR1).GT.0.0D0)THEN - GRREGLOG=LOG(EXPR1) - LOGSW*TWOPII - ELSE - GRREGLOG=LOG(EXPR1) + LOGSW*TWOPII - ENDIF - ENDIF - ENDIF - END - - MODULE B0F_CACHING - - TYPE B0F_NODE - DOUBLE COMPLEX P2,M12,M22 - DOUBLE COMPLEX VALUE - TYPE(B0F_NODE),POINTER::PARENT - TYPE(B0F_NODE),POINTER::LEFT - TYPE(B0F_NODE),POINTER::RIGHT - END TYPE B0F_NODE - - CONTAINS - - SUBROUTINE B0F_SEARCH(ITEM, HEAD, FIND) - IMPLICIT NONE - TYPE(B0F_NODE),POINTER,INTENT(INOUT)::HEAD,ITEM - LOGICAL,INTENT(OUT)::FIND - TYPE(B0F_NODE),POINTER::ITEM1 - INTEGER::ICOMP - FIND=.FALSE. - NULLIFY(ITEM%PARENT) - NULLIFY(ITEM%LEFT) - NULLIFY(ITEM%RIGHT) - IF(.NOT.ASSOCIATED(HEAD))THEN - HEAD => ITEM - RETURN - ENDIF - ITEM1 => HEAD - DO - ICOMP=B0F_NODE_COMPARE(ITEM,ITEM1) - IF(ICOMP.LT.0)THEN - IF(.NOT.ASSOCIATED(ITEM1%LEFT))THEN - ITEM1%LEFT => ITEM - ITEM%PARENT => ITEM1 - EXIT - ELSE - ITEM1 => ITEM1%LEFT - ENDIF - ELSEIF(ICOMP.GT.0)THEN - IF(.NOT.ASSOCIATED(ITEM1%RIGHT))THEN - ITEM1%RIGHT => ITEM - ITEM%PARENT => ITEM1 - EXIT - ELSE - ITEM1 => ITEM1%RIGHT - ENDIF - ELSE - FIND=.TRUE. - ITEM%VALUE=ITEM1%VALUE - EXIT - ENDIF - ENDDO - RETURN - END - - INTEGER FUNCTION B0F_NODE_COMPARE(ITEM1,ITEM2) RESULT(RES) - IMPLICIT NONE - TYPE(B0F_NODE),POINTER,INTENT(IN)::ITEM1,ITEM2 - RES=COMPLEX_COMPARE(ITEM1%P2,ITEM2%P2) - IF(RES.NE.0)RETURN - RES=COMPLEX_COMPARE(ITEM1%M22,ITEM2%M22) - IF(RES.NE.0)RETURN - RES=COMPLEX_COMPARE(ITEM1%M12,ITEM2%M12) - RETURN - END - - INTEGER FUNCTION REAL_COMPARE(R1,R2) RESULT(RES) - IMPLICIT NONE - DOUBLE PRECISION R1,R2 - DOUBLE PRECISION MAXR,DIFF - DOUBLE PRECISION TINY - PARAMETER (TINY=-1D-14) - MAXR=MAX(ABS(R1),ABS(R2)) - DIFF=R1-R2 - IF(MAXR.LE.1D-99.OR.ABS(DIFF)/MAX(MAXR,1D-99).LE.ABS(TINY))THEN - RES=0 - RETURN - ENDIF - IF(DIFF.GT.0D0)THEN - RES=1 - RETURN - ELSE - RES=-1 - RETURN - ENDIF - END - - INTEGER FUNCTION COMPLEX_COMPARE(C1,C2) RESULT(RES) - IMPLICIT NONE - DOUBLE COMPLEX C1,C2 - DOUBLE PRECISION R1,R2 - R1=DBLE(C1) - R2=DBLE(C2) - RES=REAL_COMPARE(R1,R2) - IF(RES.NE.0)RETURN - R1=DIMAG(C1) - R2=DIMAG(C2) - RES=REAL_COMPARE(R1,R2) - RETURN - END - - END MODULE B0F_CACHING - - DOUBLE COMPLEX FUNCTION B0F(P2,M12,M22) - USE B0F_CACHING - IMPLICIT NONE - DOUBLE COMPLEX P2,M12,M22 - DOUBLE COMPLEX ZERO,TWOPII - PARAMETER (ZERO=(0.0D0,0.0D0)) - PARAMETER (TWOPII=2.0D0*3.1415926535897932D0*(0.0D0,1.0D0)) - DOUBLE PRECISION M,M2,GA,GA2 - DOUBLE PRECISION TINY - PARAMETER (TINY=-1D-14) - DOUBLE COMPLEX LOGTERMS - DOUBLE COMPLEX LOG_TRAJECTORY - LOGICAL USE_CACHING - PARAMETER (USE_CACHING=.TRUE.) - TYPE(B0F_NODE),POINTER::ITEM - TYPE(B0F_NODE),POINTER,SAVE::B0F_BT - INTEGER INIT - SAVE INIT - DATA INIT /0/ - LOGICAL FIND - IF(M12.EQ.ZERO)THEN -C it is a special case -C refer to Eq.(5.48) in arXiv:1804.10017 - M=DBLE(P2) ! M^2 - M2=DBLE(M22) ! M2^2 - IF(M.LT.TINY.OR.M2.LT.TINY)THEN - WRITE(*,*)'ERROR:B0F is not well defined when M^2,M2^2<0' - STOP - ENDIF - M=DSQRT(DABS(M)) - M2=DSQRT(DABS(M2)) - IF(M.EQ.0D0)THEN - GA=0D0 - ELSE - GA=-DIMAG(P2)/M - ENDIF - IF(M2.EQ.0D0)THEN - GA2=0D0 - ELSE - GA2=-DIMAG(M22)/M2 - ENDIF - IF(P2.NE.M22.AND.P2.NE.ZERO.AND.M22.NE.ZERO)THEN - B0F=(M22-P2)/P2*LOG((M22-P2)/M22) - IF(M.GT.M2.AND.GA*M2.GT.GA2*M)THEN - B0F=B0F-TWOPII - ENDIF - RETURN - ELSE - WRITE(*,*)'ERROR:B0F is not supported for a simple form' - STOP - ENDIF - ENDIF -C the general case -C trajectory method as advocated in arXiv:1804.10017 (Eq.(E.47)) - IF(USE_CACHING)THEN - IF(INIT.EQ.0)THEN - NULLIFY(B0F_BT) - INIT=1 - ENDIF - ALLOCATE(ITEM) - ITEM%P2=P2 - ITEM%M12=M12 - ITEM%M22=M22 - FIND=.FALSE. - CALL B0F_SEARCH(ITEM,B0F_BT,FIND) - IF(FIND)THEN - B0F=ITEM%VALUE - DEALLOCATE(ITEM) - RETURN - ELSE - LOGTERMS=LOG_TRAJECTORY(100,P2,M12,M22) - B0F=-LOG(P2/M22)+LOGTERMS - ITEM%VALUE=B0F - RETURN - ENDIF - ELSE - LOGTERMS=LOG_TRAJECTORY(100,P2,M12,M22) - B0F=-LOG(P2/M22)+LOGTERMS - ENDIF - RETURN - END - - DOUBLE COMPLEX FUNCTION SQRT_TRAJECTORY(N_SEG,P2,M12,M22) -C only needed when p2*m12*m22=\=0 - IMPLICIT NONE - INTEGER N_SEG ! number of segments - DOUBLE COMPLEX P2,M12,M22 - DOUBLE COMPLEX ZERO,ONE - PARAMETER (ZERO=(0.0D0,0.0D0),ONE=(1.0D0,0.0D0)) - DOUBLE COMPLEX GAMMA0,GAMMA1 - DOUBLE PRECISION M,GA,DGA,GA_START - DOUBLE PRECISION GAI,INTERSECTION - DOUBLE COMPLEX ARGIM1,ARGI,P2I - DOUBLE COMPLEX GAMMA0I,GAMMA1I - DOUBLE PRECISION TINY - PARAMETER (TINY=-1D-24) - INTEGER I - DOUBLE PRECISION PREFACTOR - IF(ABS(P2*M12*M22).EQ.0D0)THEN - WRITE(*,*)'ERROR:sqrt_trajectory works when p2*m12*m22/=0' - STOP - ENDIF - M=DBLE(P2) ! M^2 - M=DSQRT(DABS(M)) - IF(M.EQ.0D0)THEN - GA=0D0 - ELSE - GA=-DIMAG(P2)/M - ENDIF -C Eq.(5.37) in arXiv:1804.10017 - GAMMA0=ONE+M12/P2-M22/P2 - GAMMA1=M12/P2-DCMPLX(0D0,1D0)*ABS(TINY)/P2 - IF(ABS(GA).EQ.0D0)THEN - SQRT_TRAJECTORY=SQRT(GAMMA0**2-4D0*GAMMA1) - RETURN - ENDIF -C segments from -DABS(tiny*Ga) to Ga - GA_START=-DABS(TINY*GA) - DGA=(GA-GA_START)/N_SEG - PREFACTOR=1D0 - GAI=GA_START - P2I=DCMPLX(M**2,-GAI*M) - GAMMA0I=ONE+M12/P2I-M22/P2I - GAMMA1I=M12/P2I-DCMPLX(0D0,1D0)*ABS(TINY)/P2I - ARGIM1=GAMMA0I**2-4D0*GAMMA1I - DO I=1,N_SEG - GAI=DGA*I+GA_START - P2I=DCMPLX(M**2,-GAI*M) - GAMMA0I=ONE+M12/P2I-M22/P2I - GAMMA1I=M12/P2I-DCMPLX(0D0,1D0)*ABS(TINY)/P2I - ARGI=GAMMA0I**2-4D0*GAMMA1I - IF(DIMAG(ARGI)*DIMAG(ARGIM1).LT.0D0)THEN - INTERSECTION=DIMAG(ARGIM1)*(DBLE(ARGI)-DBLE(ARGIM1)) - INTERSECTION=INTERSECTION/(DIMAG(ARGI)-DIMAG(ARGIM1)) - INTERSECTION=INTERSECTION-DBLE(ARGIM1) - IF(INTERSECTION.GT.0D0)THEN - PREFACTOR=-PREFACTOR - ENDIF - ENDIF - ARGIM1=ARGI - ENDDO - SQRT_TRAJECTORY=SQRT(GAMMA0**2-4D0*GAMMA1)*PREFACTOR - RETURN - END - - DOUBLE COMPLEX FUNCTION LOG_TRAJECTORY(N_SEG,P2,M12,M22) -C sum of log terms appearing in Eq.(5.35) of arXiv:1804.10017 -C only needed when p2*m12*m22=\=0 - IMPLICIT NONE -C 4 possible logarithms appearing in Eq.(5.35) of -C arXiv:1804.10017 -C log(arg(i)) with arg(i) for i=1 to 4 -C i=1: (ga_{+}-1) -C i=2: (ga_{-}-1) -C i=3: (ga_{+}-1)/ga_{+} -C i=4: (ga_{-}-1)/ga_{-} - INTEGER N_SEG ! number of segments - DOUBLE COMPLEX P2,M12,M22 - DOUBLE COMPLEX ZERO,ONE,HALF,TWOPII - PARAMETER (ZERO=(0.0D0,0.0D0),ONE=(1.0D0,0.0D0)) - PARAMETER (HALF=(0.5D0,0.0D0)) - PARAMETER (TWOPII=2.0D0*3.1415926535897932D0*(0.0D0,1.0D0)) - DOUBLE COMPLEX GAMMA0,GAMMAP,GAMMAM,SQRTTERM - DOUBLE PRECISION M,GA,DGA,GA_START - DOUBLE PRECISION GAI,INTERSECTION - DOUBLE COMPLEX ARGIM1(4),ARGI(4),P2I,SQRTTERMI - DOUBLE COMPLEX GAMMA0I,GAMMAPI,GAMMAMI - DOUBLE PRECISION TINY - PARAMETER (TINY=-1D-14) - INTEGER I,J - DOUBLE COMPLEX ADDFACTOR(4) - DOUBLE COMPLEX SQRT_TRAJECTORY - IF(ABS(P2*M12*M22).EQ.0D0)THEN - WRITE(*,*)'ERROR:log_trajectory works when p2*m12*m22/=0' - STOP - ENDIF - M=DBLE(P2) ! M^2 - M=DSQRT(DABS(M)) - IF(M.EQ.0D0)THEN - GA=0D0 - ELSE - GA=-DIMAG(P2)/M - ENDIF -C Eq.(5.36-5.38) in arXiv:1804.10017 - SQRTTERM=SQRT_TRAJECTORY(N_SEG,P2,M12,M22) - GAMMA0=ONE+M12/P2-M22/P2 - GAMMAP=HALF*(GAMMA0+SQRTTERM) - GAMMAM=HALF*(GAMMA0-SQRTTERM) - IF(ABS(GA).EQ.0D0)THEN - LOG_TRAJECTORY=-LOG(GAMMAP-ONE)-LOG(GAMMAM-ONE)+GAMMAP - $ *LOG((GAMMAP-ONE)/GAMMAP)+GAMMAM*LOG((GAMMAM-ONE)/GAMMAM) - RETURN - ENDIF -C segments from -DABS(tiny*Ga) to Ga - GA_START=-DABS(TINY*GA) - DGA=(GA-GA_START)/N_SEG - ADDFACTOR(1:4)=ZERO - GAI=GA_START - P2I=DCMPLX(M**2,-GAI*M) - SQRTTERMI=SQRT_TRAJECTORY(N_SEG,P2I,M12,M22) - GAMMA0I=ONE+M12/P2I-M22/P2I - GAMMAPI=HALF*(GAMMA0I+SQRTTERMI) - GAMMAMI=HALF*(GAMMA0I-SQRTTERMI) - ARGIM1(1)=GAMMAPI-ONE - ARGIM1(2)=GAMMAMI-ONE - ARGIM1(3)=(GAMMAPI-ONE)/GAMMAPI - ARGIM1(4)=(GAMMAMI-ONE)/GAMMAMI - DO I=1,N_SEG - GAI=DGA*I+GA_START - P2I=DCMPLX(M**2,-GAI*M) - SQRTTERMI=SQRT_TRAJECTORY(N_SEG,P2I,M12,M22) - GAMMA0I=ONE+M12/P2I-M22/P2I - GAMMAPI=HALF*(GAMMA0I+SQRTTERMI) - GAMMAMI=HALF*(GAMMA0I-SQRTTERMI) - ARGI(1)=GAMMAPI-ONE - ARGI(2)=GAMMAMI-ONE - ARGI(3)=(GAMMAPI-ONE)/GAMMAPI - ARGI(4)=(GAMMAMI-ONE)/GAMMAMI - DO J=1,4 - IF(DIMAG(ARGI(J))*DIMAG(ARGIM1(J)).LT.0D0)THEN - INTERSECTION=DIMAG(ARGIM1(J))*(DBLE(ARGI(J)) - $ -DBLE(ARGIM1(J))) - INTERSECTION=INTERSECTION/(DIMAG(ARGI(J))-DIMAG(ARGIM1(J) - $ )) - INTERSECTION=INTERSECTION-DBLE(ARGIM1(J)) - IF(INTERSECTION.GT.0D0)THEN - IF(DIMAG(ARGIM1(J)).LT.0)THEN - ADDFACTOR(J)=ADDFACTOR(J)-TWOPII - ELSE - ADDFACTOR(J)=ADDFACTOR(J)+TWOPII - ENDIF - ENDIF - ENDIF - ARGIM1(J)=ARGI(J) - ENDDO - ENDDO - LOG_TRAJECTORY=-(LOG(GAMMAP-ONE)+ADDFACTOR(1))-(LOG(GAMMAM-ONE) - $ +ADDFACTOR(2)) - LOG_TRAJECTORY=LOG_TRAJECTORY+GAMMAP*(LOG((GAMMAP-ONE)/GAMMAP) - $ +ADDFACTOR(3)) - LOG_TRAJECTORY=LOG_TRAJECTORY+GAMMAM*(LOG((GAMMAM-ONE)/GAMMAM) - $ +ADDFACTOR(4)) - RETURN - END - - DOUBLE COMPLEX FUNCTION ARG(COMNUM) - IMPLICIT NONE - DOUBLE COMPLEX COMNUM - DOUBLE COMPLEX IIM - IIM = (0.0D0,1.0D0) - IF(COMNUM.EQ.(0.0D0,0.0D0)) THEN - ARG=(0.0D0,0.0D0) - ELSE - ARG=LOG(COMNUM/ABS(COMNUM))/IIM - ENDIF - END - - - COMPLEX*32 FUNCTION MP_COND(CONDITION,TRUECASE,FALSECASE) - IMPLICIT NONE - COMPLEX*32 CONDITION,TRUECASE,FALSECASE - IF(CONDITION.EQ.(0.0E0_16,0.0E0_16)) THEN - MP_COND=TRUECASE - ELSE - MP_COND=FALSECASE - ENDIF - END - - COMPLEX*32 FUNCTION MP_CONDIF(CONDITION,TRUECASE,FALSECASE) - IMPLICIT NONE - LOGICAL CONDITION - COMPLEX*32 TRUECASE,FALSECASE - IF(CONDITION) THEN - MP_CONDIF=TRUECASE - ELSE - MP_CONDIF=FALSECASE - ENDIF - END - - COMPLEX*32 FUNCTION MP_RECMS(CONDITION,EXPR) - IMPLICIT NONE - LOGICAL CONDITION - COMPLEX*32 EXPR - IF(CONDITION)THEN - MP_RECMS=EXPR - ELSE - MP_RECMS=CMPLX(REAL(EXPR),KIND=16) - ENDIF - END - - - COMPLEX*32 FUNCTION MP_REGLOG(ARG_IN) - IMPLICIT NONE - COMPLEX*32 TWOPII - PARAMETER (TWOPII=2.0E0_16 - $ *3.14169258478796109557151794433593750E0_16*(0.0E0_16 - $ ,1.0E0_16)) - COMPLEX*32 ARG_IN - COMPLEX*32 ARG - ARG=ARG_IN - IF(ABS(IMAGPART(ARG)).EQ.0.0E0_16)THEN - ARG=CMPLX(REAL(ARG,KIND=16),0.0E0_16) - ENDIF - IF(ABS(REAL(ARG,KIND=16)).EQ.0.0E0_16)THEN - ARG=CMPLX(0.0E0_16,IMAGPART(ARG)) - ENDIF - IF(ARG.EQ.(0.0E0_16,0.0E0_16)) THEN - MP_REGLOG=(0.0E0_16,0.0E0_16) - ELSE - MP_REGLOG=LOG(ARG) - ENDIF - END - - COMPLEX*32 FUNCTION MP_REGLOGP(ARG_IN) - IMPLICIT NONE - COMPLEX*32 TWOPII - PARAMETER (TWOPII=2.0E0_16 - $ *3.14169258478796109557151794433593750E0_16*(0.0E0_16 - $ ,1.0E0_16)) - COMPLEX*32 ARG_IN - COMPLEX*32 ARG - ARG=ARG_IN - IF(ABS(IMAGPART(ARG)).EQ.0.0E0_16)THEN - ARG=CMPLX(REAL(ARG,KIND=16),0.0E0_16) - ENDIF - IF(ABS(REAL(ARG,KIND=16)).EQ.0.0E0_16)THEN - ARG=CMPLX(0.0E0_16,IMAGPART(ARG)) - ENDIF - IF(ARG.EQ.(0.0E0_16,0.0E0_16))THEN - MP_REGLOGP=(0.0E0_16,0.0E0_16) - ELSE - IF(REAL(ARG,KIND=16).LT.0.0E0_16.AND.IMAGPART(ARG) - $ .LT.0.0E0_16)THEN - MP_REGLOGP=LOG(ARG) + TWOPII - ELSE - MP_REGLOGP=LOG(ARG) - ENDIF - ENDIF - END - - COMPLEX*32 FUNCTION MP_REGLOGM(ARG_IN) - IMPLICIT NONE - COMPLEX*32 TWOPII - PARAMETER (TWOPII=2.0E0_16 - $ *3.14169258478796109557151794433593750E0_16*(0.0E0_16 - $ ,1.0E0_16)) - COMPLEX*32 ARG_IN - COMPLEX*32 ARG - ARG=ARG_IN - IF(ABS(IMAGPART(ARG)).EQ.0.0E0_16)THEN - ARG=CMPLX(REAL(ARG,KIND=16),0.0E0_16) - ENDIF - IF(ABS(REAL(ARG,KIND=16)).EQ.0.0E0_16)THEN - ARG=CMPLX(0.0E0_16,IMAGPART(ARG)) - ENDIF - IF(ARG.EQ.(0.0E0_16,0.0E0_16))THEN - MP_REGLOGM=(0.0E0_16,0.0E0_16) - ELSE - IF(REAL(ARG,KIND=16).LT.0.0E0_16.AND.IMAGPART(ARG) - $ .GT.0.0E0_16)THEN - MP_REGLOGM=LOG(ARG) - TWOPII - ELSE - MP_REGLOGM=LOG(ARG) - ENDIF - ENDIF - END - - COMPLEX*32 FUNCTION MP_REGSQRT(ARG_IN) - IMPLICIT NONE - COMPLEX*32 ARG_IN - COMPLEX*32 ARG - ARG=ARG_IN - IF(ABS(IMAGPART(ARG)).EQ.0.0E0_16)THEN - ARG=CMPLX(REAL(ARG,KIND=16),0.0E0_16) - ENDIF - IF(ABS(REAL(ARG,KIND=16)).EQ.0.0E0_16)THEN - ARG=CMPLX(0.0E0_16,IMAGPART(ARG)) - ENDIF - MP_REGSQRT=SQRT(ARG) - END - - COMPLEX*32 FUNCTION MP_GRREGLOG(LOGSW,EXPR1_IN,EXPR2_IN) - IMPLICIT NONE - COMPLEX*32 TWOPII - PARAMETER (TWOPII=2.0E0_16 - $ *3.14169258478796109557151794433593750E0_16*(0.0E0_16 - $ ,1.0E0_16)) - COMPLEX*32 EXPR1_IN,EXPR2_IN - COMPLEX*32 EXPR1,EXPR2 - REAL*16 LOGSW - REAL*16 IMAGEXPR - LOGICAL FIRSTSHEET - EXPR1=EXPR1_IN - EXPR2=EXPR2_IN - IF(ABS(IMAGPART(EXPR1)).EQ.0.0E0_16)THEN - EXPR1=CMPLX(REAL(EXPR1,KIND=16),0.0E0_16) - ENDIF - IF(ABS(REAL(EXPR1,KIND=16)).EQ.0.0E0_16)THEN - EXPR1=CMPLX(0.0E0_16,IMAGPART(EXPR1)) - ENDIF - IF(ABS(IMAGPART(EXPR2)).EQ.0.0E0_16)THEN - EXPR2=CMPLX(REAL(EXPR2,KIND=16),0.0E0_16) - ENDIF - IF(ABS(REAL(EXPR2,KIND=16)).EQ.0.0E0_16)THEN - EXPR2=CMPLX(0.0E0_16,IMAGPART(EXPR2)) - ENDIF - IF(EXPR1.EQ.(0.0E0_16,0.0E0_16))THEN - MP_GRREGLOG=(0.0E0_16,0.0E0_16) - ELSE - IMAGEXPR=IMAGPART(EXPR1)*IMAGPART(EXPR2) - FIRSTSHEET=IMAGEXPR.GE.0.0E0_16 - FIRSTSHEET=FIRSTSHEET.OR.REAL(EXPR1,KIND=16).GE.0.0E0_16 - FIRSTSHEET=FIRSTSHEET.OR.REAL(EXPR2,KIND=16).GE.0.0E0_16 - IF(FIRSTSHEET)THEN - MP_GRREGLOG=LOG(EXPR1) - ELSE - IF(IMAGPART(EXPR1).GT.0.0E0_16)THEN - MP_GRREGLOG=LOG(EXPR1) - LOGSW*TWOPII - ELSE - MP_GRREGLOG=LOG(EXPR1) + LOGSW*TWOPII - ENDIF - ENDIF - ENDIF - END - - MODULE MP_B0F_CACHING - - TYPE MP_B0F_NODE - COMPLEX*32 P2,M12,M22 - COMPLEX*32 VALUE - TYPE(MP_B0F_NODE),POINTER::PARENT - TYPE(MP_B0F_NODE),POINTER::LEFT - TYPE(MP_B0F_NODE),POINTER::RIGHT - END TYPE MP_B0F_NODE - - CONTAINS - - SUBROUTINE MP_B0F_SEARCH(ITEM, HEAD, FIND) - IMPLICIT NONE - TYPE(MP_B0F_NODE),POINTER,INTENT(INOUT)::HEAD,ITEM - LOGICAL,INTENT(OUT)::FIND - TYPE(MP_B0F_NODE),POINTER::ITEM1 - INTEGER::ICOMP - FIND=.FALSE. - NULLIFY(ITEM%PARENT) - NULLIFY(ITEM%LEFT) - NULLIFY(ITEM%RIGHT) - IF(.NOT.ASSOCIATED(HEAD))THEN - HEAD => ITEM - RETURN - ENDIF - ITEM1 => HEAD - DO - ICOMP=MP_B0F_NODE_COMPARE(ITEM,ITEM1) - IF(ICOMP.LT.0)THEN - IF(.NOT.ASSOCIATED(ITEM1%LEFT))THEN - ITEM1%LEFT => ITEM - ITEM%PARENT => ITEM1 - EXIT - ELSE - ITEM1 => ITEM1%LEFT - ENDIF - ELSEIF(ICOMP.GT.0)THEN - IF(.NOT.ASSOCIATED(ITEM1%RIGHT))THEN - ITEM1%RIGHT => ITEM - ITEM%PARENT => ITEM1 - EXIT - ELSE - ITEM1 => ITEM1%RIGHT - ENDIF - ELSE - FIND=.TRUE. - ITEM%VALUE=ITEM1%VALUE - EXIT - ENDIF - ENDDO - RETURN - END - - INTEGER FUNCTION MP_B0F_NODE_COMPARE(ITEM1,ITEM2) RESULT(RES) - IMPLICIT NONE - TYPE(MP_B0F_NODE),POINTER,INTENT(IN)::ITEM1,ITEM2 - RES=MP_COMPLEX_COMPARE(ITEM1%P2,ITEM2%P2) - IF(RES.NE.0)RETURN - RES=MP_COMPLEX_COMPARE(ITEM1%M22,ITEM2%M22) - IF(RES.NE.0)RETURN - RES=MP_COMPLEX_COMPARE(ITEM1%M12,ITEM2%M12) - RETURN - END - - INTEGER FUNCTION MP_REAL_COMPARE(R1,R2) RESULT(RES) - IMPLICIT NONE - REAL*16 R1,R2 - REAL*16 MAXR,DIFF - REAL*16 TINY - PARAMETER (TINY=-1.0E-14_16) - MAXR=MAX(ABS(R1),ABS(R2)) - DIFF=R1-R2 - IF(MAXR.LE.1.0E-99_16.OR.ABS(DIFF)/MAX(MAXR,1.0E-99_16) - $ .LE.ABS(TINY))THEN - RES=0 - RETURN - ENDIF - IF(DIFF.GT.0.0E0_16)THEN - RES=1 - RETURN - ELSE - RES=-1 - RETURN - ENDIF - END - - INTEGER FUNCTION MP_COMPLEX_COMPARE(C1,C2) RESULT(RES) - IMPLICIT NONE - COMPLEX*32 C1,C2 - REAL*16 R1,R2 - R1=REAL(C1,KIND=16) - R2=REAL(C2,KIND=16) - RES=MP_REAL_COMPARE(R1,R2) - IF(RES.NE.0)RETURN - R1=IMAGPART(C1) - R2=IMAGPART(C2) - RES=MP_REAL_COMPARE(R1,R2) - RETURN - END - - END MODULE MP_B0F_CACHING - - COMPLEX*32 FUNCTION MP_B0F(P2,M12,M22) - USE MP_B0F_CACHING - IMPLICIT NONE - COMPLEX*32 P2,M12,M22 - COMPLEX*32 ZERO,TWOPII - PARAMETER (ZERO=(0.0E0_16,0.0E0_16)) - PARAMETER (TWOPII=2.0E0_16 - $ *3.14169258478796109557151794433593750E0_16*(0.0E0_16 - $ ,1.0E0_16)) - REAL*16 M,M2,GA,GA2 - REAL*16 TINY - PARAMETER (TINY=-1.0E-14_16) - COMPLEX*32 LOGTERMS - COMPLEX*32 MP_LOG_TRAJECTORY - LOGICAL USE_CACHING - PARAMETER (USE_CACHING=.TRUE.) - TYPE(MP_B0F_NODE),POINTER::ITEM - TYPE(MP_B0F_NODE),POINTER,SAVE::B0F_BT - INTEGER INIT - SAVE INIT - DATA INIT /0/ - LOGICAL FIND - IF(M12.EQ.ZERO)THEN - M=REAL(P2,KIND=16) - M2=REAL(M22,KIND=16) - IF(M.LT.TINY.OR.M2.LT.TINY)THEN - WRITE(*,*)'ERROR:MP_B0F is not well defined when M^2' - $ //',M2^2<0' - STOP - ENDIF - M=SQRT(ABS(M)) - M2=SQRT(ABS(M2)) - IF(M.EQ.0.0E0_16)THEN - GA=0.0E0_16 - ELSE - GA=-IMAGPART(P2)/M - ENDIF - IF(M2.EQ.0.0E0_16)THEN - GA2=0.0E0_16 - ELSE - GA2=-IMAGPART(M22)/M2 - ENDIF - IF(P2.NE.M22.AND.P2.NE.ZERO.AND.M22.NE.ZERO)THEN - MP_B0F=(M22-P2)/P2*LOG((M22-P2)/M22) - IF(M.GT.M2.AND.GA*M2.GT.GA2*M)THEN - MP_B0F=MP_B0F-TWOPII - ENDIF - RETURN - ELSE - WRITE(*,*)'ERROR:MP_B0F is not supported for a simple' - $ //' form' - STOP - ENDIF - ENDIF - IF(USE_CACHING)THEN - IF(INIT.EQ.0)THEN - NULLIFY(B0F_BT) - INIT=1 - ENDIF - ALLOCATE(ITEM) - ITEM%P2=P2 - ITEM%M12=M12 - ITEM%M22=M22 - FIND=.FALSE. - CALL MP_B0F_SEARCH(ITEM, B0F_BT, FIND) - IF(FIND)THEN - MP_B0F=ITEM%VALUE - DEALLOCATE(ITEM) - RETURN - ELSE - LOGTERMS=MP_LOG_TRAJECTORY(100,P2,M12,M22) - MP_B0F=-LOG(P2/M22)+LOGTERMS - ITEM%VALUE=MP_B0F - RETURN - ENDIF - ELSE - LOGTERMS=MP_LOG_TRAJECTORY(100,P2,M12,M22) - MP_B0F=-LOG(P2/M22)+LOGTERMS - ENDIF - RETURN - END - - COMPLEX*32 FUNCTION MP_SQRT_TRAJECTORY(N_SEG,P2,M12,M22) - IMPLICIT NONE - INTEGER N_SEG - COMPLEX*32 P2,M12,M22 - COMPLEX*32 ZERO,ONE - PARAMETER (ZERO=(0.0E0_16,0.0E0_16),ONE=(1.0E0_16,0.0E0_16)) - COMPLEX*32 GAMMA0,GAMMA1 - REAL*16 M,GA,DGA,GA_START - REAL*16 GAI,INTERSECTION - COMPLEX*32 ARGIM1,ARGI,P2I - COMPLEX*32 GAMMA0I,GAMMA1I - REAL*16 TINY - PARAMETER (TINY=-1.0E-24_16) - INTEGER I - REAL*16 PREFACTOR - IF(ABS(P2*M12*M22).EQ.0.0E0_16)THEN - WRITE(*,*)'ERROR:mp_sqrt_trajectory works when p2*m12*m22' - $ //'/=0' - STOP - ENDIF - M=REAL(P2,KIND=16) - M=SQRT(ABS(M)) - IF(M.EQ.0.0E0_16)THEN - GA=0.0E0_16 - ELSE - GA=-IMAGPART(P2)/M - ENDIF - GAMMA0=ONE+M12/P2-M22/P2 - GAMMA1=M12/P2-CMPLX(0.0E0_16,1.0E0_16)*ABS(TINY)/P2 - IF(ABS(GA).EQ.0.0E0_16)THEN - MP_SQRT_TRAJECTORY=SQRT(GAMMA0**2-4.0E0_16*GAMMA1) - RETURN - ENDIF - GA_START=-ABS(TINY*GA) - DGA=(GA-GA_START)/N_SEG - PREFACTOR=1.0E0_16 - GAI=GA_START - P2I=CMPLX(M**2,-GAI*M) - GAMMA0I=ONE+M12/P2I-M22/P2I - GAMMA1I=M12/P2I-CMPLX(0.0E0_16,1.0E0_16)*ABS(TINY)/P2I - ARGIM1=GAMMA0I**2-4.0E0_16*GAMMA1I - DO I=1,N_SEG - GAI=DGA*I+GA_START - P2I=CMPLX(M**2,-GAI*M) - GAMMA0I=ONE+M12/P2I-M22/P2I - GAMMA1I=M12/P2I-CMPLX(0.0E0_16,1.0E0_16)*ABS(TINY)/P2I - ARGI=GAMMA0I**2-4.0E0_16*GAMMA1I - IF(IMAGPART(ARGI)*IMAGPART(ARGIM1).LT.0.0E0_16)THEN - INTERSECTION=IMAGPART(ARGIM1)*(REAL(ARGI,KIND=16) - $ -REAL(ARGIM1,KIND=16)) - INTERSECTION=INTERSECTION/(IMAGPART(ARGI) - $ -IMAGPART(ARGIM1)) - INTERSECTION=INTERSECTION-REAL(ARGIM1,KIND=16) - IF(INTERSECTION.GT.0.0E0_16)THEN - PREFACTOR=-PREFACTOR - ENDIF - ENDIF - ARGIM1=ARGI - ENDDO - MP_SQRT_TRAJECTORY=SQRT(GAMMA0**2-4.0E0_16*GAMMA1)*PREFACTOR - RETURN - END - - COMPLEX*32 FUNCTION MP_LOG_TRAJECTORY(N_SEG,P2,M12,M22) - IMPLICIT NONE - INTEGER N_SEG - COMPLEX*32 P2,M12,M22 - COMPLEX*32 ZERO,ONE,HALF,TWOPII - PARAMETER (ZERO=(0.0E0_16,0.0E0_16),ONE=(1.0E0_16,0.0E0_16)) - PARAMETER (HALF=(0.5E0_16,0.0E0_16)) - PARAMETER (TWOPII=2.0E0_16 - $ *3.14169258478796109557151794433593750E0_16*(0.0E0_16 - $ ,1.0E0_16)) - COMPLEX*32 GAMMA0,GAMMAP,GAMMAM,SQRTTERM - REAL*16 M,GA,DGA,GA_START - REAL*16 GAI,INTERSECTION - COMPLEX*32 ARGIM1(4),ARGI(4),P2I,SQRTTERMI - COMPLEX*32 GAMMA0I,GAMMAPI,GAMMAMI - REAL*16 TINY - PARAMETER (TINY=-1.0E-14_16) - INTEGER I,J - COMPLEX*32 ADDFACTOR(4) - COMPLEX*32 MP_SQRT_TRAJECTORY - IF(ABS(P2*M12*M22).EQ.0.0E0_16)THEN - WRITE(*,*)'ERROR:mp_log_trajectory works when p2*m12*m22' - $ //'/=0' - STOP - ENDIF - M=REAL(P2,KIND=16) - M=SQRT(ABS(M)) - IF(M.EQ.0.0E0_16)THEN - GA=0.0E0_16 - ELSE - GA=-IMAGPART(P2)/M - ENDIF - SQRTTERM=MP_SQRT_TRAJECTORY(N_SEG,P2,M12,M22) - GAMMA0=ONE+M12/P2-M22/P2 - GAMMAP=HALF*(GAMMA0+SQRTTERM) - GAMMAM=HALF*(GAMMA0-SQRTTERM) - IF(ABS(GA).EQ.0.0E0_16)THEN - MP_LOG_TRAJECTORY=-LOG(GAMMAP-ONE)-LOG(GAMMAM-ONE)+GAMMAP - $ *LOG((GAMMAP-ONE)/GAMMAP)+GAMMAM*LOG((GAMMAM-ONE)/GAMMAM) - RETURN - ENDIF - GA_START=-ABS(TINY*GA) - DGA=(GA-GA_START)/N_SEG - ADDFACTOR(1:4)=ZERO - GAI=GA_START - P2I=CMPLX(M**2,-GAI*M) - SQRTTERMI=MP_SQRT_TRAJECTORY(N_SEG,P2I,M12,M22) - GAMMA0I=ONE+M12/P2I-M22/P2I - GAMMAPI=HALF*(GAMMA0I+SQRTTERMI) - GAMMAMI=HALF*(GAMMA0I-SQRTTERMI) - ARGIM1(1)=GAMMAPI-ONE - ARGIM1(2)=GAMMAMI-ONE - ARGIM1(3)=(GAMMAPI-ONE)/GAMMAPI - ARGIM1(4)=(GAMMAMI-ONE)/GAMMAMI - DO I=1,N_SEG - GAI=DGA*I+GA_START - P2I=CMPLX(M**2,-GAI*M) - SQRTTERMI=MP_SQRT_TRAJECTORY(N_SEG,P2I,M12,M22) - GAMMA0I=ONE+M12/P2I-M22/P2I - GAMMAPI=HALF*(GAMMA0I+SQRTTERMI) - GAMMAMI=HALF*(GAMMA0I-SQRTTERMI) - ARGI(1)=GAMMAPI-ONE - ARGI(2)=GAMMAMI-ONE - ARGI(3)=(GAMMAPI-ONE)/GAMMAPI - ARGI(4)=(GAMMAMI-ONE)/GAMMAMI - DO J=1,4 - IF(IMAGPART(ARGI(J))*IMAGPART(ARGIM1(J)).LT.0.0E0_16)THEN - INTERSECTION=IMAGPART(ARGIM1(J))*(REAL(ARGI(J),KIND=16) - $ -REAL(ARGIM1(J),KIND=16)) - INTERSECTION=INTERSECTION/(IMAGPART(ARGI(J)) - $ -IMAGPART(ARGIM1(J))) - INTERSECTION=INTERSECTION-REAL(ARGIM1(J),KIND=16) - IF(INTERSECTION.GT.0.0E0_16)THEN - IF(IMAGPART(ARGIM1(J)).LT.0.0E0_16)THEN - ADDFACTOR(J)=ADDFACTOR(J)-TWOPII - ELSE - ADDFACTOR(J)=ADDFACTOR(J)+TWOPII - ENDIF - ENDIF - ENDIF - ARGIM1(J)=ARGI(J) - ENDDO - ENDDO - MP_LOG_TRAJECTORY=-(LOG(GAMMAP-ONE)+ADDFACTOR(1)) - $ -(LOG(GAMMAM-ONE)+ADDFACTOR(2)) - MP_LOG_TRAJECTORY=MP_LOG_TRAJECTORY+GAMMAP*(LOG((GAMMAP-ONE) - $ /GAMMAP)+ADDFACTOR(3)) - MP_LOG_TRAJECTORY=MP_LOG_TRAJECTORY+GAMMAM*(LOG((GAMMAM-ONE) - $ /GAMMAM)+ADDFACTOR(4)) - RETURN - END - - COMPLEX*32 FUNCTION MP_ARG(COMNUM) - IMPLICIT NONE - COMPLEX*32 COMNUM - COMPLEX*32 IMM - IMM = (0.0E0_16,1.0E0_16) - IF(COMNUM.EQ.(0.0E0_16,0.0E0_16)) THEN - MP_ARG=(0.0E0_16,0.0E0_16) - ELSE - MP_ARG=LOG(COMNUM/ABS(COMNUM))/IMM - ENDIF - END diff --git a/UNITTEST_proc/Source/MODEL/model_functions.inc b/UNITTEST_proc/Source/MODEL/model_functions.inc deleted file mode 100644 index 226ecdc380..0000000000 --- a/UNITTEST_proc/Source/MODEL/model_functions.inc +++ /dev/null @@ -1,32 +0,0 @@ -ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c written by the UFO converter -ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc - - DOUBLE COMPLEX COND - DOUBLE COMPLEX CONDIF - DOUBLE COMPLEX REGLOG - DOUBLE COMPLEX REGLOGP - DOUBLE COMPLEX REGLOGM - DOUBLE COMPLEX REGSQRT - DOUBLE COMPLEX GRREGLOG - DOUBLE COMPLEX RECMS - DOUBLE COMPLEX ARG - DOUBLE COMPLEX B0F - DOUBLE COMPLEX SQRT_TRAJECTORY - DOUBLE COMPLEX LOG_TRAJECTORY - - - COMPLEX*32 MP_COND - COMPLEX*32 MP_CONDIF - COMPLEX*32 MP_REGLOG - COMPLEX*32 MP_REGLOGP - COMPLEX*32 MP_REGLOGM - COMPLEX*32 MP_REGSQRT - COMPLEX*32 MP_GRREGLOG - COMPLEX*32 MP_RECMS - COMPLEX*32 MP_ARG - COMPLEX*32 MP_B0F - COMPLEX*32 MP_SQRT_TRAJECTORY - COMPLEX*32 MP_LOG_TRAJECTORY - - diff --git a/UNITTEST_proc/Source/MODEL/mp_coupl.inc b/UNITTEST_proc/Source/MODEL/mp_coupl.inc deleted file mode 100644 index 22d5fb5b98..0000000000 --- a/UNITTEST_proc/Source/MODEL/mp_coupl.inc +++ /dev/null @@ -1,44 +0,0 @@ -ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c written by the UFO converter -ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc - - REAL*16 MP__G - COMMON/MP_STRONG/ MP__G - - COMPLEX*32 MP__GAL(2) - COMMON/MP_WEAK/ MP__GAL - - COMPLEX*32 MP__MU_R - COMMON/MP_RSCALE/ MP__MU_R - - - REAL*16 MP__MDL_MB,MP__MDL_MH,MP__MDL_MT,MP__MDL_MTA,MP__MDL_MW - $ ,MP__MDL_MZ - - COMMON/MP_MASSES/ MP__MDL_MB,MP__MDL_MH,MP__MDL_MT,MP__MDL_MTA - $ ,MP__MDL_MW,MP__MDL_MZ - - - REAL*16 MP__MDL_WH,MP__MDL_WT,MP__MDL_WW,MP__MDL_WZ - - COMMON/MP_WIDTHS/ MP__MDL_WH,MP__MDL_WT,MP__MDL_WW,MP__MDL_WZ - - - COMPLEX*32 MP__GC_4,MP__GC_5,MP__GC_6,MP__R2_3GQ,MP__R2_3GG - $ ,MP__R2_GQQ,MP__R2_GGQ,MP__R2_GGB,MP__R2_GGT,MP__R2_GGG_1 - $ ,MP__R2_GGG_2,MP__R2_QQQ,MP__R2_QQT,MP__UV_3GG_1EPS - $ ,MP__UV_3GB_1EPS,MP__UV_GQQG_1EPS,MP__UV_GQQB_1EPS - $ ,MP__UV_TMASS_1EPS,MP__UVWFCT_B_0_1EPS,MP__UVWFCT_G_1_1EPS - $ ,MP__UV_3GB,MP__UV_3GT,MP__UV_GQQB,MP__UV_GQQT,MP__UV_TMASS - $ ,MP__UVWFCT_T_0,MP__UVWFCT_G_1,MP__UVWFCT_G_2 - - COMMON/MP_COUPLINGS/ MP__GC_4,MP__GC_5,MP__GC_6,MP__R2_3GQ - $ ,MP__R2_3GG,MP__R2_GQQ,MP__R2_GGQ,MP__R2_GGB,MP__R2_GGT - $ ,MP__R2_GGG_1,MP__R2_GGG_2,MP__R2_QQQ,MP__R2_QQT - $ ,MP__UV_3GG_1EPS,MP__UV_3GB_1EPS,MP__UV_GQQG_1EPS - $ ,MP__UV_GQQB_1EPS,MP__UV_TMASS_1EPS,MP__UVWFCT_B_0_1EPS - $ ,MP__UVWFCT_G_1_1EPS,MP__UV_3GB,MP__UV_3GT,MP__UV_GQQB - $ ,MP__UV_GQQT,MP__UV_TMASS,MP__UVWFCT_T_0,MP__UVWFCT_G_1 - $ ,MP__UVWFCT_G_2 - - diff --git a/UNITTEST_proc/Source/MODEL/mp_coupl_same_name.inc b/UNITTEST_proc/Source/MODEL/mp_coupl_same_name.inc deleted file mode 100644 index 6046aa3364..0000000000 --- a/UNITTEST_proc/Source/MODEL/mp_coupl_same_name.inc +++ /dev/null @@ -1,37 +0,0 @@ -ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c written by the UFO converter -ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc - - REAL*16 G - COMMON/MP_STRONG/ G - - COMPLEX*32 GAL(2) - COMMON/MP_WEAK/ GAL - - COMPLEX*32 MU_R - COMMON/MP_RSCALE/ MU_R - - - REAL*16 MDL_MB,MDL_MH,MDL_MT,MDL_MTA,MDL_MW,MDL_MZ - - COMMON/MP_MASSES/ MDL_MB,MDL_MH,MDL_MT,MDL_MTA,MDL_MW,MDL_MZ - - - REAL*16 MDL_WH,MDL_WT,MDL_WW,MDL_WZ - - COMMON/MP_WIDTHS/ MDL_WH,MDL_WT,MDL_WW,MDL_WZ - - - COMPLEX*32 GC_4,GC_5,GC_6,R2_3GQ,R2_3GG,R2_GQQ,R2_GGQ,R2_GGB - $ ,R2_GGT,R2_GGG_1,R2_GGG_2,R2_QQQ,R2_QQT,UV_3GG_1EPS,UV_3GB_1EPS - $ ,UV_GQQG_1EPS,UV_GQQB_1EPS,UV_TMASS_1EPS,UVWFCT_B_0_1EPS - $ ,UVWFCT_G_1_1EPS,UV_3GB,UV_3GT,UV_GQQB,UV_GQQT,UV_TMASS - $ ,UVWFCT_T_0,UVWFCT_G_1,UVWFCT_G_2 - - COMMON/MP_COUPLINGS/ GC_4,GC_5,GC_6,R2_3GQ,R2_3GG,R2_GQQ,R2_GGQ - $ ,R2_GGB,R2_GGT,R2_GGG_1,R2_GGG_2,R2_QQQ,R2_QQT,UV_3GG_1EPS - $ ,UV_3GB_1EPS,UV_GQQG_1EPS,UV_GQQB_1EPS,UV_TMASS_1EPS - $ ,UVWFCT_B_0_1EPS,UVWFCT_G_1_1EPS,UV_3GB,UV_3GT,UV_GQQB,UV_GQQT - $ ,UV_TMASS,UVWFCT_T_0,UVWFCT_G_1,UVWFCT_G_2 - - diff --git a/UNITTEST_proc/Source/MODEL/mp_couplings1.f b/UNITTEST_proc/Source/MODEL/mp_couplings1.f deleted file mode 100644 index 204304467d..0000000000 --- a/UNITTEST_proc/Source/MODEL/mp_couplings1.f +++ /dev/null @@ -1,16 +0,0 @@ -ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c written by the UFO converter -ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc - - SUBROUTINE MP_COUP1( ) - USE MODEL_OBJECT - IMPLICIT NONE - - INCLUDE 'model_functions.inc' - REAL*16 MP__PI, MP__ZERO - PARAMETER (MP__PI=3.1415926535897932384626433832795E0_16) - PARAMETER (MP__ZERO=0E0_16) - INCLUDE 'mp_input.inc' - INCLUDE 'mp_coupl.inc' - - END diff --git a/UNITTEST_proc/Source/MODEL/mp_couplings2.f b/UNITTEST_proc/Source/MODEL/mp_couplings2.f deleted file mode 100644 index b69c61d50d..0000000000 --- a/UNITTEST_proc/Source/MODEL/mp_couplings2.f +++ /dev/null @@ -1,16 +0,0 @@ -ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c written by the UFO converter -ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc - - SUBROUTINE MP_COUP2( ) - USE MODEL_OBJECT - IMPLICIT NONE - - INCLUDE 'model_functions.inc' - REAL*16 MP__PI, MP__ZERO - PARAMETER (MP__PI=3.1415926535897932384626433832795E0_16) - PARAMETER (MP__ZERO=0E0_16) - INCLUDE 'mp_input.inc' - INCLUDE 'mp_coupl.inc' - - END diff --git a/UNITTEST_proc/Source/MODEL/mp_couplings3.f b/UNITTEST_proc/Source/MODEL/mp_couplings3.f deleted file mode 100644 index 1b1a1d5cca..0000000000 --- a/UNITTEST_proc/Source/MODEL/mp_couplings3.f +++ /dev/null @@ -1,80 +0,0 @@ -ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c written by the UFO converter -ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc - - SUBROUTINE MP_COUP3( ) - USE MODEL_OBJECT - IMPLICIT NONE - - INCLUDE 'model_functions.inc' - REAL*16 MP__PI, MP__ZERO - PARAMETER (MP__PI=3.1415926535897932384626433832795E0_16) - PARAMETER (MP__ZERO=0E0_16) - INCLUDE 'mp_input.inc' - INCLUDE 'mp_coupl.inc' - - MP__GC_4 = -MP__G - MP__GC_5 = MP__MDL_COMPLEXI*MP__G - MP__GC_6 = MP__MDL_COMPLEXI*MP__MDL_G__EXP__2 - MP__R2_3GQ = 2.000000E+00_16*MP__MDL_G__EXP__3/(4.800000E+01_16 - $ *MP__PI**2) - MP__R2_3GG = MP__MDL_NCOL*MP__MDL_G__EXP__3/(4.800000E+01_16 - $ *MP__PI**2)*(7.000000E+00_16/4.000000E+00_16+MP__MDL_LHV) - MP__R2_GQQ = -MP__MDL_COMPLEXI*MP__MDL_G__EXP__3/(1.600000E - $ +01_16*MP__PI**2)*((MP__MDL_NCOL__EXP__2-1.000000E+00_16) - $ /(2.000000E+00_16*MP__MDL_NCOL))*(1.000000E+00_16+MP__MDL_LHV) - MP__R2_GGQ = (2.000000E+00_16)*MP__MDL_COMPLEXI - $ *MP__MDL_G__EXP__2/(4.800000E+01_16*MP__PI**2) - MP__R2_GGB = (2.000000E+00_16)*MP__MDL_COMPLEXI - $ *MP__MDL_G__EXP__2*(-6.000000E+00_16*MP__MDL_MB__EXP__2) - $ /(4.800000E+01_16*MP__PI**2) - MP__R2_GGT = (2.000000E+00_16)*MP__MDL_COMPLEXI - $ *MP__MDL_G__EXP__2*(-6.000000E+00_16*MP__MDL_MT__EXP__2) - $ /(4.800000E+01_16*MP__PI**2) - MP__R2_GGG_1 = (2.000000E+00_16)*MP__MDL_COMPLEXI - $ *MP__MDL_G__EXP__2*MP__MDL_NCOL/(4.800000E+01_16*MP__PI**2) - $ *(1.000000E+00_16/2.000000E+00_16+MP__MDL_LHV) - MP__R2_GGG_2 = -(2.000000E+00_16)*MP__MDL_COMPLEXI - $ *MP__MDL_G__EXP__2*MP__MDL_NCOL/(4.800000E+01_16*MP__PI**2) - $ *MP__MDL_LHV - MP__R2_QQQ = MP__MDL_LHV*MP__MDL_COMPLEXI*MP__MDL_G__EXP__2 - $ *(MP__MDL_NCOL__EXP__2-1.000000E+00_16)/(3.200000E+01_16*MP__PI - $ **2*MP__MDL_NCOL) - MP__R2_QQT = MP__MDL_LHV*MP__MDL_COMPLEXI*MP__MDL_G__EXP__2 - $ *(MP__MDL_NCOL__EXP__2-1.000000E+00_16)*(2.000000E+00_16 - $ *MP__MDL_MT)/(3.200000E+01_16*MP__PI**2*MP__MDL_NCOL) - MP__UV_3GG_1EPS = -MP__MDL_G_UVG_1EPS_*MP__G - MP__UV_3GB_1EPS = -MP__MDL_G_UVB_1EPS_*MP__G - MP__UV_GQQG_1EPS = MP__MDL_COMPLEXI*MP__MDL_G_UVG_1EPS_*MP__G - MP__UV_GQQB_1EPS = MP__MDL_COMPLEXI*MP__MDL_G_UVB_1EPS_*MP__G - MP__UV_TMASS_1EPS = MP__MDL_TMASS_UV_1EPS_ - MP__UVWFCT_B_0_1EPS = MP_COND(CMPLX(MP__MDL_MB,KIND=16) - $ ,CMPLX(0.000000E+00_16,KIND=16),CMPLX(-((MP__MDL_G__EXP__2) - $ /(2.000000E+00_16*1.600000E+01_16*MP__PI**2))*3.000000E+00_16 - $ *MP__MDL_CF,KIND=16)) - MP__UVWFCT_G_1_1EPS = MP_COND(CMPLX(MP__MDL_MB,KIND=16) - $ ,CMPLX(0.000000E+00_16,KIND=16),CMPLX(-((MP__MDL_G__EXP__2) - $ /(2.000000E+00_16*4.800000E+01_16*MP__PI**2))*4.000000E+00_16 - $ *MP__MDL_TF,KIND=16)) - MP__UV_3GB = -MP__MDL_G_UVB_FIN_*MP__G - MP__UV_3GT = -MP__MDL_G_UVT_FIN_*MP__G - MP__UV_GQQB = MP__MDL_COMPLEXI*MP__MDL_G_UVB_FIN_*MP__G - MP__UV_GQQT = MP__MDL_COMPLEXI*MP__MDL_G_UVT_FIN_*MP__G - MP__UV_TMASS = MP__MDL_TMASS_UV_FIN_ - MP__UVWFCT_T_0 = MP_COND(CMPLX(MP__MDL_MT,KIND=16) - $ ,CMPLX(0.000000E+00_16,KIND=16),CMPLX(-((MP__MDL_G__EXP__2) - $ /(2.000000E+00_16*1.600000E+01_16*MP__PI**2))*MP__MDL_CF - $ *(4.000000E+00_16-3.000000E+00_16 - $ *MP_REGLOG(CMPLX((MP__MDL_MT__EXP__2/MP__MDL_MU_R__EXP__2) - $ ,KIND=16))),KIND=16)) - MP__UVWFCT_G_1 = MP_COND(CMPLX(MP__MDL_MB,KIND=16) - $ ,CMPLX(0.000000E+00_16,KIND=16),CMPLX(((MP__MDL_G__EXP__2) - $ /(2.000000E+00_16*4.800000E+01_16*MP__PI**2))*4.000000E+00_16 - $ *MP__MDL_TF*MP_REGLOG(CMPLX((MP__MDL_MB__EXP__2 - $ /MP__MDL_MU_R__EXP__2),KIND=16)),KIND=16)) - MP__UVWFCT_G_2 = MP_COND(CMPLX(MP__MDL_MT,KIND=16) - $ ,CMPLX(0.000000E+00_16,KIND=16),CMPLX(((MP__MDL_G__EXP__2) - $ /(2.000000E+00_16*4.800000E+01_16*MP__PI**2))*4.000000E+00_16 - $ *MP__MDL_TF*MP_REGLOG(CMPLX((MP__MDL_MT__EXP__2 - $ /MP__MDL_MU_R__EXP__2),KIND=16)),KIND=16)) - END diff --git a/UNITTEST_proc/Source/MODEL/mp_input.inc b/UNITTEST_proc/Source/MODEL/mp_input.inc deleted file mode 100644 index bbdb87fb29..0000000000 --- a/UNITTEST_proc/Source/MODEL/mp_input.inc +++ /dev/null @@ -1,56 +0,0 @@ -ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c written by the UFO converter -ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc - - REAL*16 MP__MDL_SQRT__AS,MP__MDL_G__EXP__4,MP__MDL_G__EXP__2 - $ ,MP__MDL_G_UVG_1EPS_,MP__MDL_G_UVB_1EPS_,MP__MDL_G__EXP__3 - $ ,MP__MDL_MU_R__EXP__2,MP__MDL_G_UVB_FIN_,MP__MDL_G_UVT_FIN_ - $ ,MP__MDL_LHV,MP__MDL_CONJG__CKM3X3,MP__MDL_CONJG__CKM22 - $ ,MP__MDL_CKM3X3,MP__MDL_CKM33,MP__MDL_CKM22,MP__MDL_NCOL - $ ,MP__MDL_CA,MP__MDL_TF,MP__MDL_CF,MP__MDL_MZ__EXP__2 - $ ,MP__MDL_MZ__EXP__4,MP__MDL_SQRT__2,MP__MDL_MH__EXP__2 - $ ,MP__MDL_NCOL__EXP__2,MP__MDL_MB__EXP__2,MP__MDL_MT__EXP__2 - $ ,MP__MDL_AEW,MP__MDL_SQRT__AEW,MP__MDL_EE,MP__MDL_VECTORAUP - $ ,MP__MDL_VECTORADOWN,MP__MDL_EE__EXP__2,MP__MDL_MW__EXP__2 - $ ,MP__MDL_SW2,MP__MDL_CW,MP__MDL_SQRT__SW2,MP__MDL_SW,MP__MDL_G1 - $ ,MP__MDL_GW,MP__MDL_V,MP__MDL_V__EXP__2,MP__MDL_LAM,MP__MDL_YB - $ ,MP__MDL_YT,MP__MDL_YTAU,MP__MDL_MUH,MP__MDL_AXIALZUP - $ ,MP__MDL_AXIALZDOWN,MP__MDL_VECTORZUP,MP__MDL_VECTORZDOWN - $ ,MP__MDL_VECTORWMDXU,MP__MDL_AXIALWMDXU,MP__MDL_VECTORWPUXD - $ ,MP__MDL_AXIALWPUXD,MP__MDL_GW__EXP__2,MP__MDL_CW__EXP__2 - $ ,MP__MDL_SW__EXP__2,MP__MDL_YB__EXP__2,MP__MDL_YT__EXP__2 - $ ,MP__AEWM1,MP__MDL_GF,MP__AS,MP__MDL_YMB,MP__MDL_YMT - $ ,MP__MDL_YMTAU - - COMMON/MP_T_PARAMS_R/ MP__MDL_SQRT__AS,MP__MDL_G__EXP__4 - $ ,MP__MDL_G__EXP__2,MP__MDL_G_UVG_1EPS_,MP__MDL_G_UVB_1EPS_ - $ ,MP__MDL_G__EXP__3,MP__MDL_MU_R__EXP__2,MP__MDL_G_UVB_FIN_ - $ ,MP__MDL_G_UVT_FIN_,MP__MDL_LHV,MP__MDL_CONJG__CKM3X3 - $ ,MP__MDL_CONJG__CKM22,MP__MDL_CKM3X3,MP__MDL_CKM33 - $ ,MP__MDL_CKM22,MP__MDL_NCOL,MP__MDL_CA,MP__MDL_TF,MP__MDL_CF - $ ,MP__MDL_MZ__EXP__2,MP__MDL_MZ__EXP__4,MP__MDL_SQRT__2 - $ ,MP__MDL_MH__EXP__2,MP__MDL_NCOL__EXP__2,MP__MDL_MB__EXP__2 - $ ,MP__MDL_MT__EXP__2,MP__MDL_AEW,MP__MDL_SQRT__AEW,MP__MDL_EE - $ ,MP__MDL_VECTORAUP,MP__MDL_VECTORADOWN,MP__MDL_EE__EXP__2 - $ ,MP__MDL_MW__EXP__2,MP__MDL_SW2,MP__MDL_CW,MP__MDL_SQRT__SW2 - $ ,MP__MDL_SW,MP__MDL_G1,MP__MDL_GW,MP__MDL_V,MP__MDL_V__EXP__2 - $ ,MP__MDL_LAM,MP__MDL_YB,MP__MDL_YT,MP__MDL_YTAU,MP__MDL_MUH - $ ,MP__MDL_AXIALZUP,MP__MDL_AXIALZDOWN,MP__MDL_VECTORZUP - $ ,MP__MDL_VECTORZDOWN,MP__MDL_VECTORWMDXU,MP__MDL_AXIALWMDXU - $ ,MP__MDL_VECTORWPUXD,MP__MDL_AXIALWPUXD,MP__MDL_GW__EXP__2 - $ ,MP__MDL_CW__EXP__2,MP__MDL_SW__EXP__2,MP__MDL_YB__EXP__2 - $ ,MP__MDL_YT__EXP__2,MP__AEWM1,MP__MDL_GF,MP__AS,MP__MDL_YMB - $ ,MP__MDL_YMT,MP__MDL_YMTAU - - - COMPLEX*32 MP__MDL_TMASS_UV_1EPS_,MP__MDL_TMASS_UV_FIN_ - $ ,MP__MDL_COMPLEXI,MP__MDL_I1X33,MP__MDL_I2X33,MP__MDL_I3X33 - $ ,MP__MDL_I4X33,MP__MDL_VECTOR_TBGP,MP__MDL_AXIAL_TBGP - $ ,MP__MDL_VECTOR_TBGM,MP__MDL_AXIAL_TBGM - - COMMON/MP_PARAMS_C/ MP__MDL_TMASS_UV_1EPS_,MP__MDL_TMASS_UV_FIN_ - $ ,MP__MDL_COMPLEXI,MP__MDL_I1X33,MP__MDL_I2X33,MP__MDL_I3X33 - $ ,MP__MDL_I4X33,MP__MDL_VECTOR_TBGP,MP__MDL_AXIAL_TBGP - $ ,MP__MDL_VECTOR_TBGM,MP__MDL_AXIAL_TBGM - - diff --git a/UNITTEST_proc/Source/MODEL/mp_intparam_definition.inc b/UNITTEST_proc/Source/MODEL/mp_intparam_definition.inc deleted file mode 100644 index e52d2947f0..0000000000 --- a/UNITTEST_proc/Source/MODEL/mp_intparam_definition.inc +++ /dev/null @@ -1,210 +0,0 @@ -ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c written by the UFO converter -ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc - -C Parameters that should not be recomputed event by event. -C - IF(READLHA) THEN - - MP__G = 2 * SQRT(MP__AS*MP__PI) ! for the first init - - MP__MDL_LHV = 1.000000E+00_16 - - MP__MDL_CONJG__CKM3X3 = 1.000000E+00_16 - - MP__MDL_CONJG__CKM22 = 1.000000E+00_16 - - MP__MDL_CKM3X3 = 1.000000E+00_16 - - MP__MDL_CKM33 = 1.000000E+00_16 - - MP__MDL_CKM22 = 1.000000E+00_16 - - MP__MDL_NCOL = 3.000000E+00_16 - - MP__MDL_CA = 3.000000E+00_16 - - MP__MDL_TF = 5.000000E-01_16 - - MP__MDL_CF = (4.000000E+00_16/3.000000E+00_16) - - MP__MDL_COMPLEXI = CMPLX(0.000000E+00_16,1.000000E+00_16 - $ ,KIND=16) - - MP__MDL_MZ__EXP__2 = MP__MDL_MZ**2 - - MP__MDL_MZ__EXP__4 = MP__MDL_MZ**4 - - MP__MDL_SQRT__2 = SQRT(CMPLX((2.000000E+00_16),KIND=16)) - - MP__MDL_MH__EXP__2 = MP__MDL_MH**2 - - MP__MDL_NCOL__EXP__2 = MP__MDL_NCOL**2 - - MP__MDL_MB__EXP__2 = MP__MDL_MB**2 - - MP__MDL_MT__EXP__2 = MP__MDL_MT**2 - - MP__MDL_AEW = 1.000000E+00_16/MP__AEWM1 - - MP__MDL_SQRT__AEW = SQRT(CMPLX((MP__MDL_AEW),KIND=16)) - - MP__MDL_EE = 2.000000E+00_16*MP__MDL_SQRT__AEW - $ *SQRT(CMPLX((MP__PI),KIND=16)) - - MP__MDL_VECTORAUP = (2.000000E+00_16*MP__MDL_EE)/3.000000E - $ +00_16 - - MP__MDL_VECTORADOWN = -(MP__MDL_EE)/3.000000E+00_16 - - MP__MDL_EE__EXP__2 = MP__MDL_EE**2 - - MP__MDL_MW = SQRT(CMPLX((MP__MDL_MZ__EXP__2/2.000000E+00_16 - $ +SQRT(CMPLX((MP__MDL_MZ__EXP__4/4.000000E+00_16-(MP__MDL_AEW - $ *MP__PI*MP__MDL_MZ__EXP__2)/(MP__MDL_GF*MP__MDL_SQRT__2)) - $ ,KIND=16))),KIND=16)) - - MP__MDL_MW__EXP__2 = MP__MDL_MW**2 - - MP__MDL_SW2 = 1.000000E+00_16-MP__MDL_MW__EXP__2 - $ /MP__MDL_MZ__EXP__2 - - MP__MDL_CW = SQRT(CMPLX((1.000000E+00_16-MP__MDL_SW2),KIND=16)) - - MP__MDL_SQRT__SW2 = SQRT(CMPLX((MP__MDL_SW2),KIND=16)) - - MP__MDL_SW = MP__MDL_SQRT__SW2 - - MP__MDL_G1 = MP__MDL_EE/MP__MDL_CW - - MP__MDL_GW = MP__MDL_EE/MP__MDL_SW - - MP__MDL_V = (2.000000E+00_16*MP__MDL_MW*MP__MDL_SW)/MP__MDL_EE - - MP__MDL_V__EXP__2 = MP__MDL_V**2 - - MP__MDL_LAM = MP__MDL_MH__EXP__2/(2.000000E+00_16 - $ *MP__MDL_V__EXP__2) - - MP__MDL_YB = (MP__MDL_YMB*MP__MDL_SQRT__2)/MP__MDL_V - - MP__MDL_YT = (MP__MDL_YMT*MP__MDL_SQRT__2)/MP__MDL_V - - MP__MDL_YTAU = (MP__MDL_YMTAU*MP__MDL_SQRT__2)/MP__MDL_V - - MP__MDL_MUH = SQRT(CMPLX((MP__MDL_LAM*MP__MDL_V__EXP__2) - $ ,KIND=16)) - - MP__MDL_AXIALZUP = (3.000000E+00_16/2.000000E+00_16)*( - $ -(MP__MDL_EE*MP__MDL_SW)/(6.000000E+00_16*MP__MDL_CW)) - $ -(1.000000E+00_16/2.000000E+00_16)*((MP__MDL_CW*MP__MDL_EE) - $ /(2.000000E+00_16*MP__MDL_SW)) - - MP__MDL_AXIALZDOWN = (-1.000000E+00_16/2.000000E+00_16)*( - $ -(MP__MDL_CW*MP__MDL_EE)/(2.000000E+00_16*MP__MDL_SW))+( - $ -3.000000E+00_16/2.000000E+00_16)*(-(MP__MDL_EE*MP__MDL_SW) - $ /(6.000000E+00_16*MP__MDL_CW)) - - MP__MDL_VECTORZUP = (1.000000E+00_16/2.000000E+00_16) - $ *((MP__MDL_CW*MP__MDL_EE)/(2.000000E+00_16*MP__MDL_SW)) - $ +(5.000000E+00_16/2.000000E+00_16)*(-(MP__MDL_EE*MP__MDL_SW) - $ /(6.000000E+00_16*MP__MDL_CW)) - - MP__MDL_VECTORZDOWN = (1.000000E+00_16/2.000000E+00_16)*( - $ -(MP__MDL_CW*MP__MDL_EE)/(2.000000E+00_16*MP__MDL_SW))+( - $ -1.000000E+00_16/2.000000E+00_16)*(-(MP__MDL_EE*MP__MDL_SW) - $ /(6.000000E+00_16*MP__MDL_CW)) - - MP__MDL_VECTORWMDXU = (1.000000E+00_16/2.000000E+00_16) - $ *((MP__MDL_EE)/(MP__MDL_SW*MP__MDL_SQRT__2)) - - MP__MDL_AXIALWMDXU = (-1.000000E+00_16/2.000000E+00_16) - $ *((MP__MDL_EE)/(MP__MDL_SW*MP__MDL_SQRT__2)) - - MP__MDL_VECTORWPUXD = (1.000000E+00_16/2.000000E+00_16) - $ *((MP__MDL_EE)/(MP__MDL_SW*MP__MDL_SQRT__2)) - - MP__MDL_AXIALWPUXD = -(1.000000E+00_16/2.000000E+00_16) - $ *((MP__MDL_EE)/(MP__MDL_SW*MP__MDL_SQRT__2)) - - MP__MDL_I1X33 = MP__MDL_YB*MP__MDL_CONJG__CKM3X3 - - MP__MDL_I2X33 = MP__MDL_YT*MP__MDL_CONJG__CKM3X3 - - MP__MDL_I3X33 = MP__MDL_CKM3X3*MP__MDL_YT - - MP__MDL_I4X33 = MP__MDL_CKM3X3*MP__MDL_YB - - MP__MDL_VECTOR_TBGP = MP__MDL_I1X33-MP__MDL_I2X33 - - MP__MDL_AXIAL_TBGP = -MP__MDL_I2X33-MP__MDL_I1X33 - - MP__MDL_VECTOR_TBGM = MP__MDL_I3X33-MP__MDL_I4X33 - - MP__MDL_AXIAL_TBGM = -MP__MDL_I4X33-MP__MDL_I3X33 - - MP__MDL_GW__EXP__2 = MP__MDL_GW**2 - - MP__MDL_CW__EXP__2 = MP__MDL_CW**2 - - MP__MDL_SW__EXP__2 = MP__MDL_SW**2 - - MP__MDL_YB__EXP__2 = MP__MDL_YB**2 - - MP__MDL_YT__EXP__2 = MP__MDL_YT**2 - - ENDIF -C -C Parameters that should be recomputed at an event by even basis. -C - MP__AS = MP__G**2/4/MP__PI - - MP__MDL_SQRT__AS = SQRT(CMPLX((MP__AS),KIND=16)) - - MP__MDL_G__EXP__4 = MP__G**4 - - MP__MDL_G__EXP__2 = MP__G**2 - - MP__MDL_G__EXP__3 = MP__G**3 - - MP__MDL_MU_R__EXP__2 = MP__MU_R**2 - -C -C Parameters that should be updated for the loops. -C - MP__MDL_G_UVG_1EPS_ = -((MP__MDL_G__EXP__2)/(2.000000E+00_16 - $ *4.800000E+01_16*MP__PI**2))*1.100000E+01_16*MP__MDL_CA - - MP__MDL_G_UVB_1EPS_ = ((MP__MDL_G__EXP__2)/(2.000000E+00_16 - $ *4.800000E+01_16*MP__PI**2))*4.000000E+00_16*MP__MDL_TF - - MP__MDL_TMASS_UV_1EPS_ = MP_COND(CMPLX(MP__MDL_MT,KIND=16) - $ ,CMPLX(0.000000E+00_16,KIND=16),CMPLX(MP__MDL_COMPLEXI - $ *((MP__MDL_G__EXP__2)/(1.600000E+01_16*MP__PI**2))*3.000000E - $ +00_16*MP__MDL_CF*MP__MDL_MT,KIND=16)) - - MP__MDL_G_UVB_FIN_ = MP_COND(CMPLX(MP__MDL_MB,KIND=16) - $ ,CMPLX(0.000000E+00_16,KIND=16),CMPLX(-((MP__MDL_G__EXP__2) - $ /(2.000000E+00_16*4.800000E+01_16*MP__PI**2))*4.000000E+00_16 - $ *MP__MDL_TF*MP_REGLOG(CMPLX((MP__MDL_MB__EXP__2 - $ /MP__MDL_MU_R__EXP__2),KIND=16)),KIND=16)) - - MP__MDL_G_UVT_FIN_ = MP_COND(CMPLX(MP__MDL_MT,KIND=16) - $ ,CMPLX(0.000000E+00_16,KIND=16),CMPLX(-((MP__MDL_G__EXP__2) - $ /(2.000000E+00_16*4.800000E+01_16*MP__PI**2))*4.000000E+00_16 - $ *MP__MDL_TF*MP_REGLOG(CMPLX((MP__MDL_MT__EXP__2 - $ /MP__MDL_MU_R__EXP__2),KIND=16)),KIND=16)) - - MP__MDL_TMASS_UV_FIN_ = MP_COND(CMPLX(MP__MDL_MT,KIND=16) - $ ,CMPLX(0.000000E+00_16,KIND=16),CMPLX(MP__MDL_COMPLEXI - $ *((MP__MDL_G__EXP__2)/(1.600000E+01_16*MP__PI**2))*MP__MDL_CF - $ *(4.000000E+00_16-3.000000E+00_16 - $ *MP_REGLOG(CMPLX((MP__MDL_MT__EXP__2/MP__MDL_MU_R__EXP__2) - $ ,KIND=16)))*MP__MDL_MT,KIND=16)) - -C -C Definition of the EW coupling used in the write out of aqed -C - MP__GAL(1) = 2 * SQRT(MP__PI/ABS(MP__AEWM1)) - MP__GAL(2) = 1D0 - diff --git a/UNITTEST_proc/Source/MODEL/param_card_rule.dat b/UNITTEST_proc/Source/MODEL/param_card_rule.dat deleted file mode 100644 index 4c8b5702fc..0000000000 --- a/UNITTEST_proc/Source/MODEL/param_card_rule.dat +++ /dev/null @@ -1,25 +0,0 @@ -###################################################################### -## VALIDITY RULE FOR THE PARAM_CARD #### -###################################################################### - - wolfenstein 1 # - wolfenstein 2 # - wolfenstein 3 # - wolfenstein 4 # - yukawa 4 # - yukawa 11 # - yukawa 13 # - mass 4 # - mass 11 # - mass 13 # - decay 15 # - - - - - - - - - - \ No newline at end of file diff --git a/UNITTEST_proc/Source/MODEL/param_read.inc b/UNITTEST_proc/Source/MODEL/param_read.inc deleted file mode 100644 index 896f6b6780..0000000000 --- a/UNITTEST_proc/Source/MODEL/param_read.inc +++ /dev/null @@ -1,57 +0,0 @@ -ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c written by the UFO converter -ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc - - CALL LHA_GET_REAL_SILENT(NPARA,PARAM,VALUE,'MU_R',MU_R,9.118800D - $ +01) - CALL MP_LHA_GET_REAL_SILENT(NPARA,PARAM,VALUE,'MU_R',MP__MU_R - $ ,9.118800E+01_16) - CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'aEWM1',AEWM1,1.325070D+02) - CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'aEWM1',MP__AEWM1 - $ ,1.325070E+02_16) - CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_Gf',MDL_GF,1.166390D-05) - CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_Gf',MP__MDL_GF - $ ,1.166390E-05_16) - CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'aS',AS,1.180000D-01) - CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'aS',MP__AS,1.180000E - $ -01_16) - CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_ymb',MDL_YMB,4.700000D - $ +00) - CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_ymb',MP__MDL_YMB - $ ,4.700000E+00_16) - CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_ymt',MDL_YMT,1.730000D - $ +02) - CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_ymt',MP__MDL_YMT - $ ,1.730000E+02_16) - CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_ymtau',MDL_YMTAU - $ ,1.777000D+00) - CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_ymtau',MP__MDL_YMTAU - $ ,1.777000E+00_16) - CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_MT',MDL_MT,1.730000D+02) - CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_MT',MP__MDL_MT - $ ,1.730000E+02_16) - CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_MB',MDL_MB,4.700000D+00) - CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_MB',MP__MDL_MB - $ ,4.700000E+00_16) - CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_MZ',MDL_MZ,9.118800D+01) - CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_MZ',MP__MDL_MZ - $ ,9.118800E+01_16) - CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_MH',MDL_MH,1.250000D+02) - CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_MH',MP__MDL_MH - $ ,1.250000E+02_16) - CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_MTA',MDL_MTA,1.777000D - $ +00) - CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_MTA',MP__MDL_MTA - $ ,1.777000E+00_16) - CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_WT',MDL_WT,1.491500D+00) - CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_WT',MP__MDL_WT - $ ,1.491500E+00_16) - CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_WZ',MDL_WZ,2.441404D+00) - CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_WZ',MP__MDL_WZ - $ ,2.441404E+00_16) - CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_WW',MDL_WW,2.047600D+00) - CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_WW',MP__MDL_WW - $ ,2.047600E+00_16) - CALL LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_WH',MDL_WH,6.382339D-03) - CALL MP_LHA_GET_REAL(NPARA,PARAM,VALUE,'mdl_WH',MP__MDL_WH - $ ,6.382339E-03_16) diff --git a/UNITTEST_proc/Source/MODEL/param_write.inc b/UNITTEST_proc/Source/MODEL/param_write.inc deleted file mode 100644 index af52890124..0000000000 --- a/UNITTEST_proc/Source/MODEL/param_write.inc +++ /dev/null @@ -1,100 +0,0 @@ -ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c written by the UFO converter -ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc - - WRITE(*,*) ' External Params' - WRITE(*,*) ' ---------------------------------' - WRITE(*,*) ' ' - WRITE(*,*) 'MU_R = ', MU_R - WRITE(*,*) 'mdl_MB = ', MDL_MB - WRITE(*,*) 'mdl_MT = ', MDL_MT - WRITE(*,*) 'mdl_MTA = ', MDL_MTA - WRITE(*,*) 'mdl_MZ = ', MDL_MZ - WRITE(*,*) 'mdl_MH = ', MDL_MH - WRITE(*,*) 'aEWM1 = ', AEWM1 - WRITE(*,*) 'mdl_Gf = ', MDL_GF - WRITE(*,*) 'aS = ', AS - WRITE(*,*) 'mdl_ymb = ', MDL_YMB - WRITE(*,*) 'mdl_ymt = ', MDL_YMT - WRITE(*,*) 'mdl_ymtau = ', MDL_YMTAU - WRITE(*,*) 'mdl_WT = ', MDL_WT - WRITE(*,*) 'mdl_WZ = ', MDL_WZ - WRITE(*,*) 'mdl_WW = ', MDL_WW - WRITE(*,*) 'mdl_WH = ', MDL_WH - WRITE(*,*) ' Internal Params' - WRITE(*,*) ' ---------------------------------' - WRITE(*,*) ' ' - WRITE(*,*) 'mdl_lhv = ', MDL_LHV - WRITE(*,*) 'mdl_conjg__CKM3x3 = ', MDL_CONJG__CKM3X3 - WRITE(*,*) 'mdl_conjg__CKM22 = ', MDL_CONJG__CKM22 - WRITE(*,*) 'mdl_CKM3x3 = ', MDL_CKM3X3 - WRITE(*,*) 'mdl_CKM33 = ', MDL_CKM33 - WRITE(*,*) 'mdl_CKM22 = ', MDL_CKM22 - WRITE(*,*) 'mdl_Ncol = ', MDL_NCOL - WRITE(*,*) 'mdl_CA = ', MDL_CA - WRITE(*,*) 'mdl_TF = ', MDL_TF - WRITE(*,*) 'mdl_CF = ', MDL_CF - WRITE(*,*) 'mdl_complexi = ', MDL_COMPLEXI - WRITE(*,*) 'mdl_MZ__exp__2 = ', MDL_MZ__EXP__2 - WRITE(*,*) 'mdl_MZ__exp__4 = ', MDL_MZ__EXP__4 - WRITE(*,*) 'mdl_sqrt__2 = ', MDL_SQRT__2 - WRITE(*,*) 'mdl_MH__exp__2 = ', MDL_MH__EXP__2 - WRITE(*,*) 'mdl_Ncol__exp__2 = ', MDL_NCOL__EXP__2 - WRITE(*,*) 'mdl_MB__exp__2 = ', MDL_MB__EXP__2 - WRITE(*,*) 'mdl_MT__exp__2 = ', MDL_MT__EXP__2 - WRITE(*,*) 'mdl_aEW = ', MDL_AEW - WRITE(*,*) 'mdl_sqrt__aEW = ', MDL_SQRT__AEW - WRITE(*,*) 'mdl_ee = ', MDL_EE - WRITE(*,*) 'mdl_VectorAUp = ', MDL_VECTORAUP - WRITE(*,*) 'mdl_VectorADown = ', MDL_VECTORADOWN - WRITE(*,*) 'mdl_ee__exp__2 = ', MDL_EE__EXP__2 - WRITE(*,*) 'mdl_MW = ', MDL_MW - WRITE(*,*) 'mdl_MW__exp__2 = ', MDL_MW__EXP__2 - WRITE(*,*) 'mdl_sw2 = ', MDL_SW2 - WRITE(*,*) 'mdl_cw = ', MDL_CW - WRITE(*,*) 'mdl_sqrt__sw2 = ', MDL_SQRT__SW2 - WRITE(*,*) 'mdl_sw = ', MDL_SW - WRITE(*,*) 'mdl_g1 = ', MDL_G1 - WRITE(*,*) 'mdl_gw = ', MDL_GW - WRITE(*,*) 'mdl_v = ', MDL_V - WRITE(*,*) 'mdl_v__exp__2 = ', MDL_V__EXP__2 - WRITE(*,*) 'mdl_lam = ', MDL_LAM - WRITE(*,*) 'mdl_yb = ', MDL_YB - WRITE(*,*) 'mdl_yt = ', MDL_YT - WRITE(*,*) 'mdl_ytau = ', MDL_YTAU - WRITE(*,*) 'mdl_muH = ', MDL_MUH - WRITE(*,*) 'mdl_AxialZUp = ', MDL_AXIALZUP - WRITE(*,*) 'mdl_AxialZDown = ', MDL_AXIALZDOWN - WRITE(*,*) 'mdl_VectorZUp = ', MDL_VECTORZUP - WRITE(*,*) 'mdl_VectorZDown = ', MDL_VECTORZDOWN - WRITE(*,*) 'mdl_VectorWmDxU = ', MDL_VECTORWMDXU - WRITE(*,*) 'mdl_AxialWmDxU = ', MDL_AXIALWMDXU - WRITE(*,*) 'mdl_VectorWpUxD = ', MDL_VECTORWPUXD - WRITE(*,*) 'mdl_AxialWpUxD = ', MDL_AXIALWPUXD - WRITE(*,*) 'mdl_I1x33 = ', MDL_I1X33 - WRITE(*,*) 'mdl_I2x33 = ', MDL_I2X33 - WRITE(*,*) 'mdl_I3x33 = ', MDL_I3X33 - WRITE(*,*) 'mdl_I4x33 = ', MDL_I4X33 - WRITE(*,*) 'mdl_Vector_tbGp = ', MDL_VECTOR_TBGP - WRITE(*,*) 'mdl_Axial_tbGp = ', MDL_AXIAL_TBGP - WRITE(*,*) 'mdl_Vector_tbGm = ', MDL_VECTOR_TBGM - WRITE(*,*) 'mdl_Axial_tbGm = ', MDL_AXIAL_TBGM - WRITE(*,*) 'mdl_gw__exp__2 = ', MDL_GW__EXP__2 - WRITE(*,*) 'mdl_cw__exp__2 = ', MDL_CW__EXP__2 - WRITE(*,*) 'mdl_sw__exp__2 = ', MDL_SW__EXP__2 - WRITE(*,*) 'mdl_yb__exp__2 = ', MDL_YB__EXP__2 - WRITE(*,*) 'mdl_yt__exp__2 = ', MDL_YT__EXP__2 - WRITE(*,*) ' Internal Params evaluated point by point' - WRITE(*,*) ' ----------------------------------------' - WRITE(*,*) ' ' - WRITE(*,*) 'mdl_sqrt__aS = ', MDL_SQRT__AS - WRITE(*,*) 'mdl_G__exp__4 = ', MDL_G__EXP__4 - WRITE(*,*) 'mdl_G__exp__2 = ', MDL_G__EXP__2 - WRITE(*,*) 'mdl_G_UVg_1EPS_ = ', MDL_G_UVG_1EPS_ - WRITE(*,*) 'mdl_G_UVb_1EPS_ = ', MDL_G_UVB_1EPS_ - WRITE(*,*) 'mdl_tMass_UV_1EPS_ = ', MDL_TMASS_UV_1EPS_ - WRITE(*,*) 'mdl_G__exp__3 = ', MDL_G__EXP__3 - WRITE(*,*) 'mdl_MU_R__exp__2 = ', MDL_MU_R__EXP__2 - WRITE(*,*) 'mdl_G_UVb_FIN_ = ', MDL_G_UVB_FIN_ - WRITE(*,*) 'mdl_G_UVt_FIN_ = ', MDL_G_UVT_FIN_ - WRITE(*,*) 'mdl_tMass_UV_FIN_ = ', MDL_TMASS_UV_FIN_ diff --git a/UNITTEST_proc/Source/MODEL/printout.f b/UNITTEST_proc/Source/MODEL/printout.f deleted file mode 100644 index 5b578a9c25..0000000000 --- a/UNITTEST_proc/Source/MODEL/printout.f +++ /dev/null @@ -1,40 +0,0 @@ -ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c written by the UFO converter -ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc - -c************************************************************************ -c** ** -c** MadGraph/MadEvent Interface to FeynRules ** -c** ** -c** C. Duhr (Louvain U.) - M. Herquet (NIKHEF) ** -c** ** -c************************************************************************ - - subroutine printout - use model_object - implicit none - - - include 'coupl.inc' ! needs VECSIZE_MEMMAX (defined in vector.inc) - include 'input.inc' - - include 'formats.inc' - - write(*,*) '*****************************************************' - write(*,*) '* MadGraph/MadEvent *' - write(*,*) '* -------------------------------- *' - write(*,*) '* http://madgraph.hep.uiuc.edu *' - write(*,*) '* http://madgraph.phys.ucl.ac.be *' - write(*,*) '* http://madgraph.roma2.infn.it *' - write(*,*) '* -------------------------------- *' - write(*,*) '* *' - write(*,*) '* PARAMETER AND COUPLING VALUES *' - write(*,*) '* *' - write(*,*) '*****************************************************' - write(*,*) - - include 'param_write.inc' - include 'coupl_write.inc' - - return - end diff --git a/UNITTEST_proc/Source/MODEL/rw_para.f b/UNITTEST_proc/Source/MODEL/rw_para.f deleted file mode 100644 index b1e7a382e0..0000000000 --- a/UNITTEST_proc/Source/MODEL/rw_para.f +++ /dev/null @@ -1,97 +0,0 @@ -c************************************************************************ -c** ** -c** MadGraph/MadEvent Interface to FeynRules ** -c** ** -c** C. Duhr (Louvain U.) - M. Herquet (NIKHEF) ** -c** ** -c************************************************************************ - - subroutine setpara(param_name) - use model_object - implicit none - - character*(*) param_name - logical readlha - - include 'coupl.inc' - include 'input.inc' - include 'model_functions.inc' - include 'mp_coupl.inc' - include 'mp_input.inc' - - integer maxpara - parameter (maxpara=5000) - - integer npara - character*20 param(maxpara),value(maxpara) - - logical updateloop - common /to_updateloop/updateloop - data updateloop /.true./ - - call LHA_loadcard(param_name,npara,param,value) - ! also loop parameters should be initialised here - if (updateloop) then - include 'param_read.inc' - call coup() - else - updateloop=.true. - include 'param_read.inc' - call coup() - updateloop=.false. - endif - return - - end - - subroutine setParamLog(OnOff) - - logical OnOff - logical WriteParamLog - data WriteParamLog/.TRUE./ - common/IOcontrol/WriteParamLog - - WriteParamLog = OnOff - - end - - subroutine setpara2(param_name) - implicit none - - character(512) param_name - - integer k - logical found - - character(512) ParamCardPath - common/ParamCardPath/ParamCardPath - - if (param_name(1:1).ne.' ') then - ! Save the basename of the param_card for the ident_card. - ! If no absolute path was used then this ParamCardPath - ! remains empty - ParamCardPath = '.' - k = LEN(param_name) - found = .False. - do while (k.ge.1.and..not.found) - if (param_name(k:k).eq.'/') then - found=.True. - endif - k=k-1 - enddo - if (k.ge.1) then - ParamCardPath(1:k)=param_name(1:k) - endif - call setpara(param_name) - endif - if (param_name(1:1).eq.'*') then - ! Dummy call to printout so that it is available in the - ! dynamic library for MadLoop BLHA2 - ! In principle the --whole-archive option of ld could be - ! used but it is not always supported - call printout() - call setParamLog(.True.) - endif - return - - end diff --git a/UNITTEST_proc/Source/MODEL/testprog.f b/UNITTEST_proc/Source/MODEL/testprog.f deleted file mode 100644 index 32dc93e98c..0000000000 --- a/UNITTEST_proc/Source/MODEL/testprog.f +++ /dev/null @@ -1,72 +0,0 @@ -c************************************************************************ -c** ** -c** MadGraph/MadEvent Interface to FeynRules ** -c** ** -c** C. Duhr (Louvain U.) - M. Herquet (NIKHEF) ** -c** ** -c************************************************************************ - - program testprog - - call setpara('param_card.dat') - - - - call printout - - end - -c$$$c -c$$$c program testing the running. need to modify the makefile accordingly -c$$$c -c$$$ program testprog -c$$$ implicit none -c$$$c define the function that run alphas -c$$$ DOUBLE PRECISION ALPHAS -c$$$ EXTERNAL ALPHAS -c$$$c get the value of gs -c$$$ include '../coupl.inc' -c$$$c for initialization of the running -c$$$ include "../alfas.inc" -c$$$c include parameter from the run_card (usefull for the running) -c$$$ INCLUDE '../maxparticles.inc' -c$$$c INCLUDE '../run.inc' -c$$$c local -c$$$ integer i -c$$$ double precision mu,as -c$$$ -c$$$c -c$$$c Scales -c$$$c -c$$$ real*8 scale,scalefact,alpsfact,mue_ref_fixed,mue_over_ref -c$$$ logical fixed_ren_scale,fixed_fac_scale1, fixed_fac_scale2,fixed_couplings,hmult -c$$$ logical fixed_extra_scale -c$$$ integer ickkw,nhmult,asrwgtflavor, dynamical_scale_choice,ievo_eva -c$$$ -c$$$ common/to_scale/scale,scalefact,alpsfact, mue_ref_fixed, mue_over_ref, -c$$$ $ fixed_ren_scale,fixed_fac_scale1, fixed_fac_scale2, -c$$$ $ fixed_couplings, fixed_extra_scale,ickkw,nhmult,hmult,asrwgtflavor, -c$$$ $ dynamical_scale_choice -c$$$ -c$$$ -c$$$ -c$$$c read the param_card -c$$$ call setpara('param_card.dat') -c$$$c define your running for as... -c$$$ fixed_extra_scale = .false. -c$$$ asmz = G**2/(16d0*atan(1d0)) -c$$$ nloop = 2 -c$$$ MUE_OVER_REF = 1d0 -c$$$ -c$$$c loop for the running -c$$$ do i=1,200 -c$$$ scale = 10*i -c$$$ G = SQRT(4d0*PI*ALPHAS(scale)) -c$$$ call UPDATE_AS_PARAM() -c$$$ call printout -c$$$ enddo -c$$$ -c$$$ -c$$$ end -c$$$ -c$$$ diff --git a/UNITTEST_proc/Source/coupl.inc b/UNITTEST_proc/Source/coupl.inc deleted file mode 120000 index 6f1ad911bc..0000000000 --- a/UNITTEST_proc/Source/coupl.inc +++ /dev/null @@ -1 +0,0 @@ -MODEL/coupl.inc \ No newline at end of file diff --git a/UNITTEST_proc/Source/make_opts b/UNITTEST_proc/Source/make_opts deleted file mode 100644 index 38ad3a74fc..0000000000 --- a/UNITTEST_proc/Source/make_opts +++ /dev/null @@ -1,132 +0,0 @@ -DEFAULT_F2PY_COMPILER=f2py -DEFAULT_F_COMPILER=gfortran -MACFLAG=-mmacosx-version-min=10.7 -DEFAULT_CPP_COMPILER=clang -MG5AMC_VERSION=SpecifiedByMG5aMCAtRunTime -STDLIB=-lstdc++ -PYTHIA8_PATH=NotInstalled -STDLIB_FLAG= -#end_of_make_opts_variables - -BIASLIBDIR=../../../lib/ -BIASLIBRARY=libbias.$(libext) - -# Rest of the makefile -ifeq ($(origin FFLAGS),undefined) -FFLAGS= -w -fPIC -#FFLAGS+= -g -fbounds-check -ffpe-trap=invalid,zero,overflow,underflow,denormal -Wall -endif - -FFLAGS += $(GLOBAL_FLAG) - -# REMOVE MACFLAG IF NOT ON MAC OR FOR F2PY -UNAME := $(shell uname -s) -ifdef f2pymode -MACFLAG= -else -ifneq ($(UNAME), Darwin) -MACFLAG= -endif -endif - -# set the flag for dynamical library -ifeq ($(UNAME), Darwin) -DYNLIBFLAG=-dynamiclib -RPATHFLAG=-install_name @rpath/ -else -DYNLIBFLAG=-shared -fPIC -RPATHFLAG=-Wl,-soname, -endif - -ifeq ($(origin CXXFLAGS),undefined) -CXXFLAGS= -O $(STDLIB_FLAG) $(MACFLAG) -endif - -ifeq ($(origin CFLAGS),undefined) -CFLAGS= -O $(STDLIB_FLAG) $(MACFLAG) -endif - -# Set FC unless it's defined by an environment variable -ifeq ($(origin FC),default) -FC=$(DEFAULT_F_COMPILER) -endif -ifeq ($(origin F2PY), undefined) -F2PY=$(DEFAULT_F2PY_COMPILER) -endif - -# Increase the number of allowed charcters in a Fortran line -ifeq ($(FC), ftn) -FFLAGS+= -extend-source # for ifort type of compiler -else - VERS="$(shell $(FC) --version | grep ifort -i)" - ifeq ($(VERS), "") - FFLAGS+= -ffixed-line-length-132 - else - FFLAGS+= -extend-source # for ifort type of compiler - endif -endif - - -UNAME := $(shell uname -s) -ifeq ($(origin LDFLAGS), undefined) -LDFLAGS=$(STDLIB) $(MACFLAG) -endif - -# Options: dynamic, lhapdf -# Option dynamic - -ifeq ($(UNAME), Darwin) -dylibext=dylib -else -dylibext=so -endif - -ifdef dynamic -ifeq ($(UNAME), Darwin) -libext=dylib -FFLAGS+= -fno-common -LDFLAGS += -bundle -define CREATELIB -$(FC) -dynamiclib -undefined dynamic_lookup -o $(1) $(2) -endef -else -libext=so -FFLAGS+= -fPIC -LDFLAGS += -shared -define CREATELIB -$(FC) $(FFLAGS) $(LDFLAGS) -o $(1) $(2) -endef -endif -else -libext=a -define CREATELIB -$(AR) cru $(1) $(2) -ranlib $(1) -endef -endif - -# Option lhapdf - -ifneq ($(lhapdf),) - CXXFLAGS += $(shell $(lhapdf) --cppflags) - alfas_functions=alfas_functions_lhapdf - alfas_to_clean=alfas_functions.o - llhapdf+= $(shell $(lhapdf) --cflags --libs) -lLHAPDF -# check if we need to activate c++11 (for lhapdf6.2) - ifeq ($(origin CXX),default) - ifeq ($lhapdfversion$lhapdfsubversion,62) - CXX=$(DEFAULT_CPP_COMPILER) -std=c++11 - else - CXX=$(DEFAULT_CPP_COMPILER) - endif - endif -else - alfas_functions=alfas_functions - alfas_to_clean=alfas_functions_lhapdf.o - llhapdf= -endif - -# Helper function to check MG5 version -define CHECK_MG5AMC_VERSION -python -c 'import re; from distutils.version import StrictVersion; print StrictVersion("$(MG5AMC_VERSION)") >= StrictVersion("$(1)") if re.match("^[\d\.]+$$","$(MG5AMC_VERSION)") else True;' -endef diff --git a/UNITTEST_proc/Source/makefile b/UNITTEST_proc/Source/makefile deleted file mode 100644 index d3d3be516b..0000000000 --- a/UNITTEST_proc/Source/makefile +++ /dev/null @@ -1,96 +0,0 @@ -# Definitions - -LIBDIR= ../lib/ -BINDIR= ../bin/ -PDFDIR= ./PDF/ -PWD = $(shell pwd) -CUTTOOLSDIR= $(PWD)/CutTools/ -IREGIDIR= ./IREGI/src/ - -include make_opts - -# Source files - -PROCESS= hfill.o matrix.o myamp.o -HBOOK = hfill.o hcurve.o hbook1.o hbook2.o -GENERIC = $(alfas_functions).o transpole.o invarients.o hfill.o pawgraphs.o ran1.o \ - rw_events.o rw_routines.o kin_functions.o open_file.o basecode.o setrun.o \ - run_printout.o dgauss.o readgrid.o getissud.o -INCLUDEF= coupl.inc genps.inc hbook.inc DECAY/decay.inc psample.inc cluster.inc sudgrid.inc -BANNER = write_banner.o rw_events.o ranmar.o kin_functions.o open_file.o rw_routines.o alfas_functions.o -COMBINE = combine_events.o rw_events.o ranmar.o kin_functions.o open_file.o rw_routines.o alfas_functions.o setrun.o -GENSUDGRID = gensudgrid.o is-sud.o setrun_gen.o rw_routines.o open_file.o - -# Locally compiled libraries - -LIBRARIES= $(LIBDIR)libcts.a $(LIBDIR)libiregi.a - -# Compile commands - -all: $(LIBRARIES) $(LIBDIR)libdhelas.$(libext) $(LIBDIR)libmodel.$(libext) -# Libraries -$(LIBDIR)libdhelas.$(libext): DHELAS - cd DHELAS; make -$(LIBDIR)libmodel.$(libext): MODEL - cd MODEL; make - -CutTools: $(LIBDIR)libcts.a -libcuttools: $(LIBDIR)libcts.a - -IREGI: $(LIBDIR)libiregi.a -libiregi: $(LIBDIR)libiregi.a - -$(LIBDIR)libcts.a: $(CUTTOOLSDIR) - cd $(CUTTOOLSDIR); make - ln -sf ../Source/CutTools/includects/libcts.a $(LIBDIR)libcts.a - ln -sf ../Source/CutTools/includects/mpmodule.mod $(LIBDIR)mpmodule.mod - -$(LIBDIR)libiregi.a: $(IREGIDIR) - cd $(IREGIDIR); make - ln -sf ../Source/$(IREGIDIR)libiregi.a $(LIBDIR)libiregi.a - -cleanCT: - cd $(CUTTOOLSDIR); make clean; cd .. - -cleanIR: - cd $(IREGIDIR); make clean; cd .. - -libdhelas: $(LIBDIR)libdhelas.$(libext) - -libmodel: $(LIBDIR)libmodel.$(libext) - -treatCardsLoopNoInit: - echo "Card treatment not necessary in MadLoop standalone mode." - -# Binaries - -$(BINDIR)sum_html: sum_html.o - $(FC) $(FFLAGS) -o $@ $^ -$(BINDIR)gen_ximprove: gen_ximprove.o ranmar.o rw_routines.o open_file.o - $(FC) $(FFLAGS) -o $@ $^ -$(BINDIR)combine_events: $(COMBINE) $(LIBDIR)libmodel.$(libext) $(LIBDIR)libpdf.$(libext) - $(FC) $(FFLAGS) -o $@ $(COMBINE) -L$(LIBDIR) -lmodel -lpdf $(lhapdf) -$(BINDIR)gensudgrid: $(GENSUDGRID) $(LIBDIR)libpdf.$(libext) $(LIBDIR)libcernlib.$(libext) - $(FC) $(FFLAGS) -o $@ $(GENSUDGRID) -L$(LIBDIR) -lmodel -lpdf -lcernlib $(lhapdf) -$(BINDIR)combine_runs: combine_runs.o rw_events.o - $(FC) $(FFLAGS) -o $@ $^ - -# Dependencies - -dsample.o: dsample.f genps.inc -invarients.o: invarients.f genps.inc -setrun.o: setrun.f nexternal.inc leshouche.inc genps.inc -sum_html.o: sum_html.f genps.inc -gen_ximprove.o: gen_ximprove.f run_config.inc -combine_events.o: combine_events.f run_config.inc -select_events.o: select_events.f run_config.inc -setrun.o: setrun.f nexternal.inc leshouche.inc - -clean: - rm -f *.o - rm -f param_card.inc run_card.inc - cd MODEL; make clean; cd .. - cd DHELAS; make clean; cd .. - if [ -d $(CUTTOOLSDIR) ]; then cd $(CUTTOOLSDIR); make clean; cd ..; fi - if [ -d $(STDHEPDIR) ]; then cd $(STDHEPDIR); make clean; cd ..; fi - rm -f $(BINDIR)/combine_events $(BINDIR)/gen_ximprove diff --git a/UNITTEST_proc/SubProcesses/MadLoop5_resources/ML5_0_ColorDenomFactors.dat b/UNITTEST_proc/SubProcesses/MadLoop5_resources/ML5_0_ColorDenomFactors.dat deleted file mode 100644 index c06e5148e7..0000000000 --- a/UNITTEST_proc/SubProcesses/MadLoop5_resources/ML5_0_ColorDenomFactors.dat +++ /dev/null @@ -1,129 +0,0 @@ -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 --1 3 3 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 --1 3 3 --1 3 3 --1 3 3 --1 3 3 -1 -1 -1 --1 1 1 -1 -1 -1 --1 9 9 -1 -1 -1 --1 9 9 --1 9 9 -1 -1 -1 --1 9 9 -1 -1 -1 -1 -1 -1 --1 1 1 --1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 --1 9 9 --1 9 9 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 --1 9 9 --1 9 9 -1 -1 -1 -1 -1 -1 -1 -1 -1 --1 1 1 --1 1 1 --1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 --1 3 3 --1 3 3 -1 -1 -1 --1 3 3 --1 3 3 -1 -1 -1 --1 3 3 --1 3 3 diff --git a/UNITTEST_proc/SubProcesses/MadLoop5_resources/ML5_0_ColorNumFactors.dat b/UNITTEST_proc/SubProcesses/MadLoop5_resources/ML5_0_ColorNumFactors.dat deleted file mode 100644 index 01be50116f..0000000000 --- a/UNITTEST_proc/SubProcesses/MadLoop5_resources/ML5_0_ColorNumFactors.dat +++ /dev/null @@ -1,129 +0,0 @@ -6 -3 3 -12 -6 6 -12 -6 6 -12 -6 6 -12 -6 6 -12 -6 6 -12 -6 6 -12 -6 6 -12 -6 6 -12 -6 6 -12 -6 6 -6 16 -2 -6 16 -2 -6 16 -2 -6 16 -2 -6 16 -2 -6 16 -2 -6 16 -2 -6 16 -2 -6 16 -2 -6 16 -2 -6 16 -2 -6 16 -2 -6 16 -2 --6 -2 16 --6 -2 16 --6 -2 16 --6 -2 16 --6 -2 16 --6 -2 16 --6 -2 16 --6 -2 16 --6 -2 16 --6 -2 16 --6 -2 16 --6 -2 16 --6 -2 16 --6 -2 16 --6 -2 16 --6 -2 16 --6 -2 16 --6 -2 16 --6 -2 16 --6 -2 16 --6 -2 16 --6 -2 16 --6 -2 16 -6 16 -2 -6 16 -2 -6 16 -2 -6 16 -2 -6 16 -2 -6 16 -2 -6 16 -2 -6 16 -2 -6 16 -2 -6 16 -2 -12 -6 6 -12 -6 6 -12 -6 6 -12 -6 6 -12 -6 6 -12 -6 6 -12 -6 6 -12 -6 6 -12 -6 6 -12 -6 6 -6 -3 3 -6 -3 3 -6 -3 3 -6 -3 3 -12 -6 6 -12 -6 6 -12 -6 6 -12 -6 6 -6 -3 3 -12 -6 6 -6 -3 3 -12 -6 6 -12 -6 6 -12 -6 6 -6 16 -2 -6 16 -2 --6 -2 16 --6 -2 16 --36 18 -18 -18 9 -9 --2 1 -1 -8 64 -8 -9 -8 1 --1 -8 1 --8 -8 64 -9 -1 8 -1 1 -8 --9 1 -8 --9 8 -1 --9 -9 0 -9 0 -9 --18 9 -9 -36 -18 18 -18 -9 9 --18 9 -9 -0 -1 -1 -1 1 -8 --1 -8 1 --36 18 -18 --18 9 -9 -18 -9 9 -0 1 1 --1 1 10 -1 10 1 -36 -18 18 -18 -9 9 --18 9 -9 --18 -9 9 --9 0 9 -9 9 0 -36 -18 18 --18 9 -9 -18 -9 9 --6 3 -3 -3 2 -7 --3 -7 2 --6 3 -3 -3 2 -7 --3 -7 2 --6 3 -3 -3 2 -7 --3 -7 2 diff --git a/UNITTEST_proc/SubProcesses/MadLoop5_resources/ML5_0_HelConfigs.dat b/UNITTEST_proc/SubProcesses/MadLoop5_resources/ML5_0_HelConfigs.dat deleted file mode 100644 index 9bd09cc180..0000000000 --- a/UNITTEST_proc/SubProcesses/MadLoop5_resources/ML5_0_HelConfigs.dat +++ /dev/null @@ -1,16 +0,0 @@ --1 -1 -1 1 --1 -1 -1 -1 --1 -1 1 1 --1 -1 1 -1 --1 1 -1 1 --1 1 -1 -1 --1 1 1 1 --1 1 1 -1 -1 -1 -1 1 -1 -1 -1 -1 -1 -1 1 1 -1 -1 1 -1 -1 1 -1 1 -1 1 -1 -1 -1 1 1 1 -1 1 1 -1 diff --git a/UNITTEST_proc/SubProcesses/MadLoop5_resources/MadLoopParams.dat b/UNITTEST_proc/SubProcesses/MadLoop5_resources/MadLoopParams.dat deleted file mode 120000 index e783cc88dd..0000000000 --- a/UNITTEST_proc/SubProcesses/MadLoop5_resources/MadLoopParams.dat +++ /dev/null @@ -1 +0,0 @@ -../MadLoopParams.dat \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/MadLoop5_resources/ident_card.dat b/UNITTEST_proc/SubProcesses/MadLoop5_resources/ident_card.dat deleted file mode 120000 index 89e64bf2ef..0000000000 --- a/UNITTEST_proc/SubProcesses/MadLoop5_resources/ident_card.dat +++ /dev/null @@ -1 +0,0 @@ -../../Cards/ident_card.dat \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/MadLoop5_resources/param_card.dat b/UNITTEST_proc/SubProcesses/MadLoop5_resources/param_card.dat deleted file mode 120000 index 44928ac167..0000000000 --- a/UNITTEST_proc/SubProcesses/MadLoop5_resources/param_card.dat +++ /dev/null @@ -1 +0,0 @@ -../../Cards/param_card.dat \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/MadLoopCommons.f b/UNITTEST_proc/SubProcesses/MadLoopCommons.f deleted file mode 100644 index a97b549812..0000000000 --- a/UNITTEST_proc/SubProcesses/MadLoopCommons.f +++ /dev/null @@ -1,682 +0,0 @@ - SUBROUTINE JOINPATH(STR1,STR2,PATH) - - CHARACTER*(*) STR1 - CHARACTER*(*) STR2 - CHARACTER*(*) PATH - - INTEGER I,J,K - - I =1 - DO WHILE (I.LE.LEN(STR1)) - IF(STR1(I:I).EQ.' ') GOTO 800 - PATH(I:I) = STR1(I:I) - I=I+1 - ENDDO - 800 CONTINUE - J=1 - DO WHILE (J.LE.LEN(STR2)) - IF(STR2(J:J).EQ.' ') GOTO 801 - PATH(I-1+J:I-1+J) = STR2(J:J) - J=J+1 - ENDDO - 801 CONTINUE - K=I+J-1 - DO WHILE (K.LE.LEN(PATH)) - PATH(K:K) = ' ' - K=K+1 - ENDDO - - RETURN - - END - - - - SUBROUTINE SET_FORBID_HEL_DOUBLECHECK(ONOFF) -C -C Give the possibility to overwrite the value of MadLoopParams.dat -C for the helicity double checking. -C Make sure to call this subroutine before the first time you -C call MadLoop. -C - IMPLICIT NONE -C -C ARGUMENT -C - LOGICAL ONOFF -C -C GLOBAL VARIABLES -C - LOGICAL FORBID_HEL_DOUBLECHECK - DATA FORBID_HEL_DOUBLECHECK/.FALSE./ - COMMON/FORBID_HEL_DOUBLECHECK/FORBID_HEL_DOUBLECHECK -C ---------- -C BEGIN CODE -C ---------- - FORBID_HEL_DOUBLECHECK = ONOFF - END - - SUBROUTINE SETMADLOOPPATH(PATH) - - CHARACTER(512) PATH - CHARACTER(512) DUMMY - CHARACTER(512) EPATH ! path of the executable - INTEGER POS - CHARACTER(512) PREFIX,FPATH - CHARACTER(17) NAMETOCHECK - PARAMETER (NAMETOCHECK='MadLoopParams.dat') - - LOGICAL ML_INIT - DATA ML_INIT/.TRUE./ - COMMON/ML_INIT/ML_INIT - - LOGICAL CTINIT,TIRINIT,GOLEMINIT,SAMURAIINIT,NINJAINIT - $ ,COLLIERINIT - DATA CTINIT,TIRINIT,GOLEMINIT,SAMURAIINIT,NINJAINIT,COLLIERINIT - $ /.TRUE.,.TRUE.,.TRUE.,.TRUE.,.TRUE.,.TRUE./ - COMMON/REDUCTIONCODEINIT/CTINIT, TIRINIT, GOLEMINIT, SAMURAIINIT - $ , NINJAINIT, COLLIERINIT - - - CHARACTER(512) MLPATH - DATA MLPATH/'[[NA]]'/ - COMMON/MLPATH/MLPATH - - INTEGER I - -C Just a dummy call for LD to pick up this function -C when creating the BLHA2 dynamic library - DUMMY = ' ' - CALL SETPARA2(DUMMY) - - IF (LEN(PATH).GE.4 .AND. PATH(1:4).EQ.'auto') THEN - IF (MLPATH(1:6).EQ.'[[NA]]') THEN -C Try to automatically find the path - PREFIX='./' - CALL JOINPATH(PREFIX,NAMETOCHECK,FPATH) - OPEN(1, FILE=FPATH, ERR=1, STATUS='OLD',ACTION='READ') - MLPATH=PREFIX - GOTO 10 - 1 CONTINUE - CLOSE(1) - PREFIX='./MadLoop5_resources/' - CALL JOINPATH(PREFIX,NAMETOCHECK,FPATH) - OPEN(1, FILE=FPATH, ERR=2, STATUS='OLD',ACTION='READ') - MLPATH=PREFIX - GOTO 10 - 2 CONTINUE - CLOSE(1) - PREFIX='../MadLoop5_resources/' - CALL JOINPATH(PREFIX,NAMETOCHECK,FPATH) - OPEN(1, FILE=FPATH, ERR=3, STATUS='OLD',ACTION='READ') - MLPATH=PREFIX - GOTO 10 - 3 CONTINUE - CLOSE(1) -C -C Try to automatically find the path from the executable -C location -C particularly usefull in gridpack readonly mode -C - CALL GETARG(0,PATH) !path is the PATH to the madevent executable (either global or from launching directory) - POS = INDEX(PATH,'/',.TRUE.) - PREFIX = PATH(:POS) - CALL JOINPATH(PREFIX,NAMETOCHECK,FPATH) - WRITE(*,*) 'test', FPATH - OPEN(1, FILE=FPATH, ERR=4, STATUS='OLD',ACTION='READ') - MLPATH=PREFIX - GOTO 10 - 4 CONTINUE - CLOSE(1) - PREFIX= PREFIX // '/MadLoop5_resources/' - CALL JOINPATH(PREFIX,NAMETOCHECK,FPATH) - WRITE(*,*) 'test', FPATH - OPEN(1, FILE=FPATH, ERR=5, STATUS='OLD',ACTION='READ') - MLPATH=PREFIX - GOTO 10 - 5 CONTINUE - CLOSE(1) - PREFIX= PATH(:POS) // '/../MadLoop5_resources/' - CALL JOINPATH(PREFIX,NAMETOCHECK,FPATH) - WRITE(*,*) 'test', FPATH - OPEN(1, FILE=FPATH, ERR=6, STATUS='OLD',ACTION='READ') - MLPATH=PREFIX - GOTO 10 - 6 CONTINUE - CLOSE(1) - -C We could not automatically find the auxiliary files - WRITE(*,*) '===' - WRITE(*,*) 'ERROR: MadLoop5 could not automatically find the' - $ //' file MadLoopParams.dat.' - WRITE(*,*) '===' - WRITE(*,*) '(Try using ' - $ //' (before your first call to MadLoop) in order to set the' - $ //' directory where this file is located as well as other' - $ //' auxiliary files, such as _ColorNumFactors.dat,' - $ //' _ColorDenomFactors.dat, etc..)' - STOP - 10 CONTINUE - CLOSE(1) - RETURN - ENDIF - ELSE -C Use the one specified by the user -C Make sure there is a separator added - I =1 - DO WHILE (I.LE.LEN(PATH) .AND. PATH(I:I).NE.' ') - I=I+1 - ENDDO - IF (PATH(I-1:I-1).NE.'/') THEN - PATH(I:I) = '/' - ENDIF - MLPATH=PATH - ENDIF - -C Check that the FilePath set is correct - CALL JOINPATH(MLPATH,NAMETOCHECK,FPATH) - OPEN(1, FILE=FPATH, ERR=33, STATUS='OLD',ACTION='READ') - GOTO 11 - 33 CONTINUE - CLOSE(1) - WRITE(*,*) '===' - WRITE(*,*) 'ERROR: The MadLoop5 auxiliary files could not be' - $ //' found in ',MLPATH - WRITE(*,*) '===' - STOP - 11 CONTINUE - CLOSE(1) - - END - - INTEGER FUNCTION SET_RET_CODE_U(MLRED,DOING_QP,STABLE) -C -C This functions returns the value of U -C -C -C U == 0 -C Not stable. -C U == 1 -C Stable with CutTools in double precision. -C U == 2 -C Stable with PJFry++. -C U == 3 -C Stable with IREGI. -C U == 4 -C Stable with Golem95. -C U == 5 -C Stable with Samurai. -C U == 6 -C Stable with Ninja in double precision. -C U == 7 -C Stable with COLLIER. -C U == 8 -C Stable with Ninja in quadruple precision. -C U == 9 -C Stable with CutTools in quadruple precision. -C - IMPLICIT NONE -C -C CONSTANTS -C -C -C ARGUMENTS -C - INTEGER MLRED - LOGICAL DOING_QP,STABLE -C -C LOCAL VARIABLES -C -C -C FUNCTION -C -C -C BEGIN CODE -C - IF(.NOT.STABLE)THEN - SET_RET_CODE_U=0 - RETURN - ENDIF - IF(DOING_QP)THEN - IF(MLRED.EQ.1)THEN - SET_RET_CODE_U=9 - RETURN - ELSEIF(MLRED.EQ.6)THEN - SET_RET_CODE_U=8 - RETURN - ELSE - STOP 'Only CutTools and Ninja can use quardruple precision' - ENDIF - ENDIF - IF(MLRED.GE.1.AND.MLRED.LE.7)THEN - SET_RET_CODE_U=MLRED - ELSE - STOP 'Only CutTools, PJFry++, IREGI, Golem95, Samurai, Ninja' - $ //' and COLLIER are available' - ENDIF - END - - SUBROUTINE DETECT_LOOPLIB(LIBNUM,NLOOPLINE,RANK,COMPLEX_MASS - $ ,HAS_HEFT_VERTEX,MAX_SPIN_CONNECTED_TO_LOOP,LPASS) -C -C DETECT WHICH LOOP LIB PASSED -C - IMPLICIT NONE -C -C CONSTANTS -C -C -C ARGUMENTS -C - INTEGER LIBNUM,NLOOPLINE,RANK,MAX_SPIN_CONNECTED_TO_LOOP -C The argument HAS_HEFT_VERTEX is only to implement correctly -C CutTools limitation - LOGICAL COMPLEX_MASS,LPASS,HAS_HEFT_VERTEX -C -C LOCAL VARIABLES -C -C -C GLOBAL VARIABLES -C -C ---------- -C BEGIN CODE -C ---------- - IF(LIBNUM.EQ.1)THEN -C CutTools - CALL DETECT_CUTTOOLS(NLOOPLINE,RANK,COMPLEX_MASS - $ ,HAS_HEFT_VERTEX,MAX_SPIN_CONNECTED_TO_LOOP,LPASS) - ELSEIF(LIBNUM.EQ.2)THEN -C PJFry++ - CALL DETECT_PJFRY(NLOOPLINE,RANK,COMPLEX_MASS,LPASS) - ELSEIF(LIBNUM.EQ.3)THEN -C IREGI - CALL DETECT_IREGI(NLOOPLINE,RANK,COMPLEX_MASS,LPASS) - ELSEIF(LIBNUM.EQ.4)THEN -C Golem95 - CALL DETECT_GOLEM(NLOOPLINE,RANK,COMPLEX_MASS,LPASS) - ELSEIF(LIBNUM.EQ.5)THEN -C Samurai - CALL DETECT_SAMURAI(NLOOPLINE,RANK,COMPLEX_MASS,LPASS) - ELSEIF(LIBNUM.EQ.6)THEN -C Ninja - CALL DETECT_NINJA(NLOOPLINE,RANK,COMPLEX_MASS,LPASS) - ELSEIF(LIBNUM.EQ.7)THEN -C Collier - CALL DETECT_COLLIER(NLOOPLINE,RANK,COMPLEX_MASS,LPASS) - ELSE - STOP 'Only CutTools, PJFry++, IREGI, Golem95, Samurai, Ninja' - $ //' and COLLIER are available' - ENDIF - RETURN - END - - SUBROUTINE DETECT_CUTTOOLS(NLOOPLINE,RANK,COMPLEX_MASS - $ ,HAS_HEFT_VERTEX,MAX_SPIN_CONNECTED_TO_LOOP,LPASS) -C -C DETECT whether CUTTOOLS CAN BE USED OR NOT -C - IMPLICIT NONE - -C -C CONSTANTS -C -C -C ARGUMENTS -C - INTEGER NLOOPLINE,RANK - INTEGER MAX_SPIN_CONNECTED_TO_LOOP - LOGICAL COMPLEX_MASS,LPASS,HAS_HEFT_VERTEX -C -C LOCAL VARIABLES -C - INTEGER MAX_RANK -C ---------- -C BEGIN CODE -C ---------- - LPASS=.TRUE. -C The limit of 10 loop lines is just a parameter hardcoded in -C CutTools sources. -C It can easily be increased if necessary. -C Also in the presence of spin2 particles, RANK=NLOOPLINE+1 is not -C supported, -C or in general whenever the higher rank doesn't come from the -C Higgs effective vertex. - - IF (MAX_SPIN_CONNECTED_TO_LOOP.LE.3.AND.HAS_HEFT_VERTEX) THEN - MAX_RANK = NLOOPLINE+1 - ELSE - MAX_RANK = NLOOPLINE - ENDIF - - IF( (RANK.GT.MAX_RANK).OR.(NLOOPLINE.GT.10) ) THEN - LPASS=.FALSE. - ENDIF - - RETURN - END - - SUBROUTINE DETECT_SAMURAI(NLOOPLINE,RANK,COMPLEX_MASS,LPASS) -C -C DETECT whether Samurai CAN BE USED OR NOT -C - IMPLICIT NONE -C -C CONSTANTS -C -C -C ARGUMENTS -C - INTEGER NLOOPLINE,RANK - LOGICAL COMPLEX_MASS,LPASS -C -C LOCAL VARIABLES -C -C -C GLOBAL VARIABLES -C -C ---------- -C BEGIN CODE -C ---------- - LPASS=.TRUE. -C The limit of 8 loop lines is just a parameter hardcoded in -C Samurai sources. -C It can easily be increased if necessary. - IF((NLOOPLINE+1.LT.RANK).OR.(NLOOPLINE.GT.8)) THEN - LPASS=.FALSE. - ENDIF - RETURN - END - - SUBROUTINE DETECT_NINJA(NLOOPLINE,RANK,COMPLEX_MASS,LPASS) -C -C Detect whether Ninja can be used or not -C - IMPLICIT NONE -C -C CONSTANTS -C -C -C ARGUMENTS -C - INTEGER NLOOPLINE,RANK - LOGICAL COMPLEX_MASS,LPASS -C -C LOCAL VARIABLES -C -C -C GLOBAL VARIABLES -C -C ---------- -C BEGIN CODE -C ---------- - LPASS=.TRUE. -C The limit of rank 20 is just a parameter hardcoded in Ninja -C sources. -C It can easily be increased if necessary. - IF((NLOOPLINE+1.LT.RANK).OR.(RANK.GE.20)) THEN - LPASS=.FALSE. - ENDIF - RETURN - END - - SUBROUTINE DETECT_COLLIER(NLOOPLINE,RANK,COMPLEX_MASS,LPASS) -C -C ARGUMENTS -C - INTEGER NLOOPLINE,RANK - LOGICAL COMPLEX_MASS,LPASS -C -C COLLIER is not available in this output. This subroutine is -C dummy. -C - LPASS=.TRUE. - END - - SUBROUTINE DETECT_PJFRY(NLOOPLINE,RANK,COMPLEX_MASS,LPASS) -C -C DETECT whether PJFRY++ CAN BE USED OR NOT -C - IMPLICIT NONE -C -C CONSTANTS -C -C -C ARGUMENTS -C - INTEGER NLOOPLINE,RANK - LOGICAL COMPLEX_MASS,LPASS -C -C LOCAL VARIABLES -C -C -C GLOBAL VARIABLES -C -C ---------- -C BEGIN CODE -C ---------- - LPASS=.TRUE. - IF(NLOOPLINE.LT.RANK.OR.RANK.GT.5.OR.NLOOPLINE.GT.5.OR.COMPLEX_MA - $SS.OR.NLOOPLINE.EQ.1) THEN - LPASS=.FALSE. - ENDIF - RETURN - END - - SUBROUTINE DETECT_IREGI(NLOOPLINE,RANK,COMPLEX_MASS,LPASS) -C -C DETECT whether IREGI CAN BE USED OR NOT -C - IMPLICIT NONE -C -C CONSTANTS -C -C -C ARGUMENTS -C - INTEGER NLOOPLINE,RANK - LOGICAL COMPLEX_MASS,LPASS -C -C LOCAL VARIABLES -C -C -C GLOBAL VARIABLES -C -C ---------- -C BEGIN CODE -C ---------- -C Stability studies show that IREGI is completely unstable at rank -C 7 and above. - LPASS=.TRUE. - IF(NLOOPLINE.GE.8.OR.RANK.GE.7)LPASS=.FALSE. - RETURN - END - - SUBROUTINE DETECT_GOLEM(NLOOPLINE,RANK,COMPLEX_MASS,LPASS) -C -C DETECT whether Golem95 CAN BE USED OR NOT -C - IMPLICIT NONE -C -C CONSTANTS -C -C -C ARGUMENTS -C - INTEGER NLOOPLINE,RANK - LOGICAL COMPLEX_MASS,LPASS -C -C LOCAL VARIABLES -C -C -C GLOBAL VARIABLES -C -C ---------- -C BEGIN CODE -C ---------- - - LPASS=.TRUE. - IF(NLOOPLINE.GE.7.OR.RANK.GE.7.OR.NLOOPLINE.LE.1)LPASS=.FALSE. - IF(NLOOPLINE.LE.5.AND.RANK.GT.NLOOPLINE+1)LPASS=.FALSE. - IF(NLOOPLINE.EQ.6.AND.RANK.GT.NLOOPLINE)LPASS=.FALSE. - RETURN - END - -C Now some sorting related routines. Only to be used for small -C arrays since these are not the most optimized sorting algorithms. - -C ----------------------------------------------------------------- -C --- -C INTEGER FUNCTION FindMinimum(): -C This function returns the location of the minimum in the section -C between Start and End. -C ----------------------------------------------------------------- -C --- - - INTEGER FUNCTION FINDMINIMUM(X, MSTART, MEND) - IMPLICIT NONE - INTEGER MAXNREF_EVALS - PARAMETER (MAXNREF_EVALS=100) - DOUBLE PRECISION, DIMENSION(MAXNREF_EVALS), INTENT(IN) :: X - INTEGER, INTENT(IN) :: MSTART, MEND - INTEGER :: MINIMUM - INTEGER :: LOCATION - INTEGER :: I - - MINIMUM = X(MSTART) ! assume the first is the min - LOCATION = MSTART ! record its position - DO I = MSTART+1, MEND ! start with next elements - IF (X(I) < MINIMUM) THEN ! if x(i) less than the min? - MINIMUM = X(I) ! Yes, a new minimum found - LOCATION = I ! record its position - END IF - END DO - FINDMINIMUM = LOCATION ! return the position - END FUNCTION FINDMINIMUM - -C ----------------------------------------------------------------- -C --- -C SUBROUTINE Swap(): -C This subroutine swaps the values of its two formal arguments. -C ----------------------------------------------------------------- -C --- - - SUBROUTINE SWAP(A, B) - IMPLICIT NONE - REAL*8, INTENT(INOUT) :: A, B - REAL*8 :: TEMP - - TEMP = A - A = B - B = TEMP - END SUBROUTINE SWAP - -C ----------------------------------------------------------------- -C --- -C SUBROUTINE Sort(): -C This subroutine receives an array x() and sorts it into ascending -C order. -C ----------------------------------------------------------------- -C --- - - SUBROUTINE SORT(X, MSIZE) - IMPLICIT NONE - INTEGER MAXNREF_EVALS - PARAMETER (MAXNREF_EVALS=100) - REAL*8, DIMENSION(MAXNREF_EVALS), INTENT(INOUT) :: X - INTEGER, INTENT(IN) :: MSIZE - INTEGER :: I - INTEGER :: LOCATION - INTEGER :: FINDMINIMUM - DO I = 1, MSIZE-1 ! except for the last - LOCATION = FINDMINIMUM(X, I, MSIZE) ! find min from this to last - CALL SWAP(X(I), X(LOCATION)) ! swap this and the minimum - END DO - END SUBROUTINE SORT - -C ----------------------------------------------------------------- -C --- -C REAL*8 FUNCTION Median() : -C This function receives an array X of N entries, copies its value -C to a local array Temp(), sorts Temp() and computes the median. -C The returned value is of REAL type. -C ----------------------------------------------------------------- -C --- - - REAL*8 FUNCTION MEDIAN(X, N) - IMPLICIT NONE - INTEGER MAXNREF_EVALS - PARAMETER (MAXNREF_EVALS=100) - REAL*8, DIMENSION(MAXNREF_EVALS), INTENT(IN) :: X - INTEGER, INTENT(IN) :: N - REAL*8, DIMENSION(MAXNREF_EVALS) :: TEMP - INTEGER :: I - - DO I = 1, N ! make a copy - TEMP(I) = X(I) - END DO - CALL SORT(TEMP, N) ! sort the copy - IF (MOD(N,2) == 0) THEN ! compute the median - MEDIAN = (TEMP(N/2) + TEMP(N/2+1)) / 2.0D0 - ELSE - MEDIAN = TEMP(N/2+1) - END IF - END FUNCTION MEDIAN - - - SUBROUTINE PRINT_MADLOOP_BANNER() - - WRITE(*,*) ' ====================================================' - $ //'====================================== ' - WRITE(*,*) '{ ' - $ //' }' - WRITE(*,*) '{ '//CHAR(27)//'[32m'//' ' - $ //' '/ - $ /CHAR(27)//'[0m'//' }' - WRITE(*,*) '{ '//CHAR(27)//'[32m'//' ' - $ //' ,, '/ - $ /CHAR(27)//'[0m'//' }' - WRITE(*,*) '{ '//CHAR(27)//'[32m'//'`7MMM. ,MMF'/ - $ /CHAR(39)//' `7MM `7MMF'//CHAR(39)//' ' - $ //' '//CHAR(27)//'[0m'//' }' - WRITE(*,*) '{ '//CHAR(27)//'[32m'//' MMMb dPMM ' - $ //' MM MM '/ - $ /CHAR(27)//'[0m'//' }' - WRITE(*,*) '{ '//CHAR(27)//'[32m'//' M YM ,M MM ,6'/ - $ /CHAR(34)//'Yb. ,M'//CHAR(34)//''//CHAR(34)//'bMM MM ' - $ //' ,pW'//CHAR(34)//'Wq. ,pW'//CHAR(34)//'Wq.`7MMpdMAo. '/ - $ /CHAR(27)//'[0m'//' }' - WRITE(*,*) '{ '//CHAR(27)//'[32m'//' M Mb M'//CHAR(39)/ - $ /' MM 8) MM ,AP MM MM 6W'//CHAR(39)//' `Wb' - $ //' 6W'//CHAR(39)//' `Wb MM `Wb '//CHAR(27)//'[0m'//' ' - $ //' }' - WRITE(*,*) '{ '//CHAR(27)//'[32m'//' M YM.P'//CHAR(39)/ - $ /' MM ,pm9MM 8MI MM MM , 8M M8 8M M8 MM ' - $ //' M8 '//CHAR(27)//'[0m'//' }' - WRITE(*,*) '{ '//CHAR(27)//'[32m'//' M `YM'//CHAR(39)// - $ ' MM 8M MM `Mb MM MM ,M YA. ,A9 YA. ,A9 MM ' - $ //' ,AP '//CHAR(27)//'[0m'//' }' - WRITE(*,*) '{ '//CHAR(27)//'[32m'//'.JML. `'//CHAR(39)//' ' - $ //' .JMML.`Moo9^Yo.`Wbmd'//CHAR(34)//'MML..JMMmmmmMMM `Ybmd9'/ - $ /CHAR(39)//' `Ybmd9'//CHAR(39)//' MMbmmd'//CHAR(39)//' '/ - $ /CHAR(27)//'[0m'//' }' - WRITE(*,*) '{ '//CHAR(27)//'[32m'//' ' - $ //' MM '/ - $ /CHAR(27)//'[0m'//' }' - WRITE(*,*) '{ '//CHAR(27)//'[32m'//' ' - $ //' .JMML. '/ - $ /CHAR(27)//'[0m'//' }' - WRITE(*,*) '{ '//CHAR(27)//'[32m'//CHAR(27)//'[0m'/ - $ /'v3.7.2 (2026-04-29), Ref: arXiv:1103.0621v2, arXiv:1405.0301' - $ //CHAR(27)//'[32m'//' '//CHAR(27)//'[0m'//' ' - $ //' }' - WRITE(*,*) '{ '//CHAR(27)//'[32m'//' ' - $ //' '/ - $ /CHAR(27)//'[0m'//' }' - WRITE(*,*) '{ ' - $ //' }' - WRITE(*,*) ' ====================================================' - $ //'====================================== ' - - END - - diff --git a/UNITTEST_proc/SubProcesses/MadLoopParamReader.f b/UNITTEST_proc/SubProcesses/MadLoopParamReader.f deleted file mode 100644 index d8b4951a10..0000000000 --- a/UNITTEST_proc/SubProcesses/MadLoopParamReader.f +++ /dev/null @@ -1,343 +0,0 @@ - subroutine MadLoopParamReader(filename, printParam) - - implicit none - - CHARACTER(512) fileName, buff, buff2, mode - CHARACTER*20 MLReductionLib_str,MLReductionLib_str_save - CHARACTER*2 MLReductionLib_char - INTEGER MLRed,i,j,k - - include "MadLoopParams.inc" - - logical printParam, couldRead, paramPrinted, find - data paramPrinted/.FALSE./ - couldRead=.False. -! Default parameters - - open(666, file=fileName, err=676, status='OLD', action='READ') - do - read(666,*,end=999) buff - if(index(buff,'#').eq.1) then - - if (buff .eq. '#CTModeInit') then - read(666,*,end=999) CTModeInit - if (CTModeInit .lt. 0 .or. - & CTModeInit .gt. 6 ) then - stop 'CTModeInit must be >= 0 and <=6.' - endif - - else if (buff .eq. '#CTModeRun') then - read(666,*,end=999) CTModeRun - if (CTModeRun .lt. -1 .or. - & CTModeRun .gt. 6 ) then - stop 'CTModeRun must be >= -1 and <=6.' - endif - - else if (buff .eq. '#COLLIERGlobalCache') then - read(666,*,end=999) COLLIERGlobalCache - if (COLLIERGlobalCache .lt. -1) then - stop 'COLLIERGlobalCache must be >= -1' - endif - - else if (buff .eq. '#NRotations_DP') then - read(666,*,end=999) NRotations_DP - if (NRotations_DP .lt. 0 .or. - & NRotations_DP .gt. 2 ) then - stop 'NRotations_DP must be >= 0 and <=2.' - endif - - else if (buff .eq. '#NRotations_QP') then - read(666,*,end=999) NRotations_QP - if (NRotations_QP .lt. 0 .or. - & NRotations_QP .gt. 2 ) then - stop 'NRotations_QP must be >= 0 and <=2.' - endif - - else if (buff .eq. '#MLStabThres') then - read(666,*,end=999) MLStabThres - if (MLStabThres.lt.0.0d0) then - stop 'MLStabThres must be >= 0' - endif - - else if (buff .eq. '#COLLIERRequiredAccuracy') then - read(666,*,end=999) COLLIERRequiredAccuracy - if (COLLIERRequiredAccuracy.le.0.0d0.and. - & COLLIERRequiredAccuracy.ne.-1.0d0) then - stop 'COLLIERRequiredAccuracy must be > 0 or = -1.0' - endif - - else if (buff .eq. '#CTLoopLibrary') then - read(666,*,end=999) CTLoopLibrary - if (CTLoopLibrary.lt.2 .or. - & CTLoopLibrary.gt.3) then - stop 'CTLoopLibrary must be >= 2 and <=3.' - endif - - else if (buff .eq. '#CTStabThres') then - read(666,*,end=999) CTStabThres - if (CTStabThres.le.0.0d0) then - stop 'CTStabThres must be > 0' - endif - - else if (buff .eq. '#ZeroThres') then - read(666,*,end=999) ZeroThres - if (ZeroThres.le.0.0d0) then - stop 'ZeroThres must be > 0' - endif - - else if (buff .eq. '#OSThres') then - read(666,*,end=999) OSThres - if (OSThres.le.0.0d0) then - stop 'OSThres must be > 0' - endif - - else if (buff .eq. '#CheckCycle') then - read(666,*,end=999) CheckCycle - if (CheckCycle.lt.1) then - stop 'CheckCycle must be >= 1' - endif - - else if (buff .eq. '#MaxAttempts') then - read(666,*,end=999) MaxAttempts - if (MaxAttempts.lt.1) then - stop 'MaxAttempts must be >= 1' - endif - - else if (buff .eq. '#COLLIERComputeUVpoles') then - read(666,*,end=999) COLLIERComputeUVpoles - - else if (buff .eq. '#COLLIERComputeIRpoles') then - read(666,*,end=999) COLLIERComputeIRpoles - - else if (buff .eq. '#COLLIERUseInternalStabilityTest') then - read(666,*,end=999) COLLIERUseInternalStabilityTest - - else if (buff .eq. '#COLLIERUseCacheForPoles') then - read(666,*,end=999) COLLIERUseCacheForPoles - - else if (buff .eq. '#COLLIERCanOutput') then - read(666,*,end=999) COLLIERCanOutput - - else if (buff .eq. '#UseLoopFilter') then - read(666,*,end=999) UseLoopFilter - - else if (buff .eq. '#DoubleCheckHelicityFilter') then - read(666,*,end=999) DoubleCheckHelicityFilter - - else if (buff .eq. '#LoopInitStartOver') then - read(666,*,end=999) LoopInitStartOver - - else if (buff .eq. '#HelInitStartOver') then - read(666,*,end=999) HelInitStartOver - - else if (buff .eq. '#WriteOutFilters') then - read(666,*,end=999) WriteOutFilters - - else if (buff .eq. '#UseQPIntegrandForNinja') then - read(666,*,end=999) UseQPIntegrandForNinja - - else if (buff .eq. '#UseQPIntegrandForCutTools') then - read(666,*,end=999) UseQPIntegrandForCutTools - - else if (buff .eq. '#ImprovePSPoint') then - read(666,*,end=999) ImprovePSPoint - if (ImprovePSPoint .lt. -1 .or. - & ImprovePSPoint .gt. 2 ) then - stop 'ImprovePSPoint must be >= -1 and <=2.' - endif - - else if (buff .eq. '#HelicityFilterLevel') then - read(666,*,end=999) HelicityFilterLevel - if (HelicityFilterLevel .lt. 0 .or. - & HelicityFilterLevel .gt. 2 ) then - stop 'HelicityFilterLevel must be >= 0 and <=2.' - endif - - else if (buff .eq. '#MLReductionLib') then - read(666,*,end=999) MLReductionLib_str - MLReductionLib(1:7)=0 - MLReductionLib_str_save=MLReductionLib_str - j=0 - DO - i=index(MLReductionLib_str,'|') - IF(i.EQ.0)THEN - MLReductionLib_char=MLReductionLib_str - ELSE - MLReductionLib_char=MLReductionLib_str(:i-1) - ENDIF - IF(MLReductionLib_char.EQ.'1 ')THEN - MLRed=1 - ELSEIF(MLReductionLib_char.EQ.'2 ')THEN - MLRed=2 - ELSEIF(MLReductionLib_char.EQ.'3 ')THEN - MLRed=3 - ELSEIF(MLReductionLib_char.EQ.'4 ')THEN - MLRed=4 - ELSEIF(MLReductionLib_char.EQ.'5 ')THEN - MLRed=5 - ELSEIF(MLReductionLib_char.EQ.'6 ')THEN - MLRed=6 - ELSEIF(MLReductionLib_char.EQ.'7 ')THEN - MLRed=7 - ELSE - PRINT *, 'MLReductionLib is wrong: '// - $ TRIM(MLReductionLib_str_save) - STOP - ENDIF - find=.FALSE. - DO k=1,j - IF(MLReductionLib(k).EQ.MLRed)THEN - find=.TRUE. - EXIT - ENDIF - ENDDO - IF(.NOT.find)THEN - j=j+1 - MLReductionLib(j)=MLRed - ENDIF - IF(i.EQ.0)THEN - EXIT - ELSE - MLReductionLib_str=MLReductionLib_str(i+1:) - ENDIF - ENDDO - else if (buff .eq. '#COLLIERMode') then - read(666,*,end=999) COLLIERMode - if (COLLIERMode .lt. 1 .or. - & COLLIERMode .gt.3) then - stop 'COLLIERMode must be >=1 and <=3.' - endif - else if (buff .eq. '#IREGIRECY') then - read(666,*,end=999) IREGIRECY - else if (buff .eq. '#IREGIMODE') then - read(666,*,end=999) IREGIMODE - if (IREGIMODE .lt. 0 .or. - & IREGIMODE .gt.2) then - stop 'IREGIMODE must be >=0 and <=2.' - endif - else - write(*,*) 'The parameter name ',buff(2:), - &' is not reckognized.' - stop - endif - - endif - enddo - 999 continue - couldRead=.True. - goto 998 - - 676 continue - write(*,*) '##E00 Error:: MadLoop parameter file ',fileName, - &' could not be found or is malformed. Please specify it.' - stop -C Below is the code if one desires to let the code continue with -C a non existing or malformed parameter file - write(*,*) '##I01 INFO :: The file ',fileName,' could not be ', - & ' open or did not contain the necessary information. The ', - & ' default MadLoop parameters will be used.' - call DefaultParam() - goto 999 - - 998 continue - - if(printParam.and..not.paramPrinted) then - write(*,*) - & '===============================================================' - if (couldRead) then - write(*,*) 'INFO: MadLoop read these parameters from ' - &,filename - else - write(*,*) 'INFO: MadLoop used the default parameters.' - endif - write(*,*) - & '===============================================================' - write(*,*) ' > MLReductionLib = ' - $ //TRIM(MLReductionLib_str_save) - write(*,*) ' > CTModeRun = ',CTModeRun - write(*,*) ' > MLStabThres = ',MLStabThres - write(*,*) ' > NRotations_DP = ',NRotations_DP - write(*,*) ' > NRotations_QP = ',NRotations_QP - write(*,*) ' > CTStabThres = ',CTStabThres - write(*,*) ' > CTLoopLibrary = ',CTLoopLibrary - write(*,*) ' > CTModeInit = ',CTModeInit - write(*,*) ' > CheckCycle = ',CheckCycle - write(*,*) ' > MaxAttempts = ',MaxAttempts - write(*,*) ' > UseLoopFilter = ',UseLoopFilter - write(*,*) ' > HelicityFilterLevel = ',HelicityFilterLevel - write(*,*) ' > ImprovePSPoint = ',ImprovePSPoint - write(*,*) ' > DoubleCheckHelicityFilter = ', - &DoubleCheckHelicityFilter - write(*,*) ' > LoopInitStartOver = ',LoopInitStartOver - write(*,*) ' > HelInitStartOver = ',HelInitStartOver - write(*,*) ' > ZeroThres = ',ZeroThres - write(*,*) ' > OSThres = ',OSThres - write(*,*) ' > WriteOutFilters = ',WriteOutFilters - write(*,*) ' > UseQPIntegrandForNinja = ', - &UseQPIntegrandForNinja - write(*,*) ' > UseQPIntegrandForCutTools = ', - &UseQPIntegrandForCutTools - write(*,*) ' > IREGIMODE = ',IREGIMODE - write(*,*) ' > IREGIRECY = ',IREGIRECY - write(*,*) ' > COLLIERMode = ',COLLIERMode - write(*,*) ' > COLLIERRequiredAccuracy = ', - $COLLIERRequiredAccuracy - write(*,*) ' > COLLIERCanOutput = ',COLLIERCanOutput - write(*,*) ' > COLLIERComputeUVpoles = ',COLLIERComputeUVpoles - write(*,*) ' > COLLIERComputeIRpoles = ',COLLIERComputeIRpoles - write(*,*) ' > COLLIERGlobalCache = ',COLLIERGlobalCache - write(*,*) ' > COLLIERUseCacheForPoles = ', - &COLLIERUseCacheForPoles - write(*,*) ' > COLLIERUseInternalStabilityTest = ', - &COLLIERUseInternalStabilityTest - write(*,*) - & '===============================================================' - paramPrinted=.TRUE. - endif - - close(666) - - end - - subroutine DefaultParam() - - implicit none - - include "MadLoopParams.inc" - - MLReductionLib(1)=6 - MLReductionLib(2)=7 - MLReductionLib(3)=1 - MLReductionLib(4:7)=0 - IREGIMODE=2 - IREGIRECY=.TRUE. - COLLIERComputeIRpoles = .TRUE. - COLLIERComputeUVpoles = .TRUE. - COLLIERUseCacheForPoles = .FALSE. - COLLIERCanOutput = .FALSE. - COLLIERGlobalCache = -1 - COLLIERMode=1 - COLLIERRequiredAccuracy=1.0d-8 - COLLIERUseInternalStabilityTest = .TRUE. - CTModeInit=0 - CTModeRun=-1 - NRotations_DP=0 - NRotations_QP=0 - MLStabThres=1.0d-3 - CTStabThres=1.0d-2 - CTLoopLibrary=3 - CheckCycle=3 - MaxAttempts=10 - HelicityFilterLevel=2 - UseLoopFilter=.False. - DoubleCheckHelicityFilter=.True. - LoopInitStartOver=.False. - HelInitStartOver=.False. - WriteOutFilters=.True. - ZeroThres=1.0d-9 - OSThres=1.0d-13 - ImprovePSPoint=2 - UseQPIntegrandForCutTools=.True. - UseQPIntegrandForNinja=.True. - - end diff --git a/UNITTEST_proc/SubProcesses/MadLoopParams.dat b/UNITTEST_proc/SubProcesses/MadLoopParams.dat deleted file mode 120000 index bf9bac2770..0000000000 --- a/UNITTEST_proc/SubProcesses/MadLoopParams.dat +++ /dev/null @@ -1 +0,0 @@ -../Cards/MadLoopParams.dat \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/MadLoopParams.inc b/UNITTEST_proc/SubProcesses/MadLoopParams.inc deleted file mode 100644 index 008576b237..0000000000 --- a/UNITTEST_proc/SubProcesses/MadLoopParams.inc +++ /dev/null @@ -1,30 +0,0 @@ -!==================================================================== -! -! Define common block with all general parameters used by MadLoop -! See their definitions in the file MadLoopParams.dat -! -!==================================================================== -! - integer CTModeInit,CTModeRun,CheckCycle,MaxAttempts, - &CTLoopLibrary,NRotations_DP,NRotations_QP,ImprovePSPoint, - &MLReductionLib(8),IREGIMODE,HelicityFilterLevel,COLLIERMode, - &COLLIERGlobalCache - - real*8 MLStabThres,CTStabThres,ZeroThres,OSThres,COLLIERRequiredAccuracy - - logical UseLoopFilter,LoopInitStartOver,DoubleCheckHelicityFilter, - &COLLIERComputeIRpoles,COLLIERComputeUVpoles,COLLIERCanOutput - logical HelInitStartOver,IREGIRECY,WriteOutFilters - logical UseQPIntegrandForNinja, UseQPIntegrandForCutTools - logical COLLIERUseCacheForPoles,COLLIERUseInternalStabilityTest - - common /MADLOOP/CTModeInit,CTModeRun,NRotations_DP,NRotations_QP, - &COLLIERMode,COLLIERGlobalCache, - &ImprovePSPoint,CheckCycle, MaxAttempts,UseLoopFilter,MLStabThres, - &COLLIERRequiredAccuracy, - &CTStabThres,CTLoopLibrary,LoopInitStartOver, - &COLLIERComputeIRpoles,COLLIERComputeUVpoles,COLLIERCanOutput, - &COLLIERUseCacheForPoles,COLLIERUseInternalStabilityTest, - &DoubleCheckHelicityFilter,ZeroThres,OSThres,HelInitStartOver, - &MLReductionLib,IREGIMODE,HelicityFilterLevel,IREGIRECY, - &WriteOutFilters,UseQPIntegrandForNinja,UseQPIntegrandForCutTools diff --git a/UNITTEST_proc/SubProcesses/MadLoop_makefile_definitions b/UNITTEST_proc/SubProcesses/MadLoop_makefile_definitions deleted file mode 100644 index 85078693a1..0000000000 --- a/UNITTEST_proc/SubProcesses/MadLoop_makefile_definitions +++ /dev/null @@ -1,13 +0,0 @@ -LINK_LOOP_LIBS = -L$(LIBDIR) -lcts -LOOP_LIBS = $(LIBDIR)libcts.$(libext) -DYLOOP_LIBS = -LOOP_INCLUDE = -LOOP_PREFIX = P -DOTO = %.o -DOTF = %.f -LINK_MADLOOP_LIB = -L$(LIBDIR) -lMadLoop -MADLOOP_LIB = $(LIBDIR)libMadLoop.$(libext) -RPATH_LIBS = - -$(MADLOOP_LIB): - cd ..; make -f makefile_MadLoop OLP_static diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/CT_interface.f b/UNITTEST_proc/SubProcesses/P0_gg_ttx/CT_interface.f deleted file mode 100644 index 600104f556..0000000000 --- a/UNITTEST_proc/SubProcesses/P0_gg_ttx/CT_interface.f +++ /dev/null @@ -1,663 +0,0 @@ - SUBROUTINE ML5_0_CTLOOP(NLOOPLINE,PL,M2L,RANK,RES,STABLE) -C -C Generated by MadGraph5_aMC@NLO v. 3.7.2, 2026-04-29 -C By the MadGraph5_aMC@NLO Development Team -C Visit launchpad.net/madgraph5 and amcatnlo.web.cern.ch -C -C Interface between MG5 and CutTools. -C -C Process: g g > t t~ QCD<=2 QED=0 [ virt = QCD ] -C -C -C CONSTANTS -C - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - LOGICAL CHECKPCONSERVATION - PARAMETER (CHECKPCONSERVATION=.TRUE.) - REAL*8 NORMALIZATION - PARAMETER (NORMALIZATION = 1.D0/(16.D0*3.14159265358979323846D0* - $ *2)) -C -C ARGUMENTS -C - INTEGER NLOOPLINE, RANK - REAL*8 PL(0:3,NLOOPLINE) - REAL*8 PCT(0:3,0:NLOOPLINE-1) - COMPLEX*16 M2L(NLOOPLINE) - COMPLEX*16 M2LCT(0:NLOOPLINE-1) - COMPLEX*16 RES(3) - LOGICAL STABLE -C -C LOCAL VARIABLES -C - COMPLEX*16 R1, ACC - INTEGER I, J, K - LOGICAL CTINIT, TIRINIT, GOLEMINIT, SAMURAIINIT, NINJAINIT - COMMON/REDUCTIONCODEINIT/CTINIT,TIRINIT,GOLEMINIT,SAMURAIINIT - $ ,NINJAINIT -C -C EXTERNAL FUNCTIONS -C - EXTERNAL ML5_0_LOOPNUM - EXTERNAL ML5_0_MPLOOPNUM -C -C GLOBAL VARIABLES -C - INCLUDE 'coupl.inc' - INTEGER CTMODE - REAL*8 LSCALE - COMMON/ML5_0_CT/LSCALE,CTMODE - - INTEGER WE(NEXTERNAL) - INTEGER ID, SYMFACT, MULTIPLIER, AMPLNUM - COMMON/ML5_0_LOOP/WE,ID,SYMFACT, MULTIPLIER, AMPLNUM - -C ---------- -C BEGIN CODE -C ---------- - -C INITIALIZE CUTTOOLS IF NEEDED - IF (CTINIT) THEN - CTINIT=.FALSE. - CALL ML5_0_INITCT() - CALL CITE('Ossola:2007ax','one-loop reduction with CutTools') - ENDIF - -C YOU CAN FIND THE DETAILS ABOUT THE DIFFERENT CTMODE AT THE -C BEGINNING OF THE FILE CTS_CUTS.F90 IN THE CUTTOOLS DISTRIBUTION - -C CONVERT THE MASSES TO BE COMPLEX - DO I=1,NLOOPLINE - M2LCT(I-1)=M2L(I) - ENDDO - -C CONVERT THE MOMENTA FLOWING IN THE LOOP LINES TO CT CONVENTIONS - DO I=0,3 - DO J=0,(NLOOPLINE-1) - PCT(I,J)=0.D0 - ENDDO - ENDDO - DO I=0,3 - DO J=1,NLOOPLINE - PCT(I,0)=PCT(I,0)+PL(I,J) - ENDDO - ENDDO - IF (CHECKPCONSERVATION) THEN - IF (PCT(0,0).GT.1.D-6) THEN - WRITE(*,*) 'energy is not conserved ',PCT(0,0) - STOP 'energy is not conserved' - ELSEIF (PCT(1,0).GT.1.D-6) THEN - WRITE(*,*) 'px is not conserved ',PCT(1,0) - STOP 'px is not conserved' - ELSEIF (PCT(2,0).GT.1.D-6) THEN - WRITE(*,*) 'py is not conserved ',PCT(2,0) - STOP 'py is not conserved' - ELSEIF (PCT(3,0).GT.1.D-6) THEN - WRITE(*,*) 'pz is not conserved ',PCT(3,0) - STOP 'pz is not conserved' - ENDIF - ENDIF - DO I=0,3 - DO J=1,(NLOOPLINE-1) - DO K=1,J - PCT(I,J)=PCT(I,J)+PL(I,K) - ENDDO - ENDDO - ENDDO - - CALL CTSXCUT(CTMODE,LSCALE,MU_R,NLOOPLINE,ML5_0_LOOPNUM - $ ,ML5_0_MPLOOPNUM,RANK,PCT,M2LCT,RES,ACC,R1,STABLE) - RES(1)=NORMALIZATION*2.0D0*DBLE(RES(1)) - RES(2)=NORMALIZATION*2.0D0*DBLE(RES(2)) - RES(3)=NORMALIZATION*2.0D0*DBLE(RES(3)) -C WRITE(*,*) 'Loop AMPLNUM',AMPLNUM,' =',RES(1),RES(2),RES(3) - END - - SUBROUTINE ML5_0_INITCT() -C -C INITIALISATION OF CUTTOOLS -C -C LOCAL VARIABLES -C - REAL*8 THRS - LOGICAL EXT_NUM_FOR_R1 -C -C GLOBAL VARIABLES -C - INCLUDE 'MadLoopParams.inc' -C ---------- -C BEGIN CODE -C ---------- - -C DEFAULT PARAMETERS FOR CUTTOOLS -C ------------------------------- -C THRS1 IS THE PRECISION LIMIT BELOW WHICH THE MP ROUTINES -C ACTIVATES - THRS=CTSTABTHRES -C LOOPLIB SET WHAT LIBRARY CT USES -C 1 -> LOOPTOOLS -C 2 -> AVH -C 3 -> QCDLOOP - LOOPLIB=CTLOOPLIBRARY -C MADLOOP'S NUMERATOR IN THE DEFAULT OUTPUT IS SLOWER THAN THE -C RECONSTRUCTED ONE IN CT. SO WE BETTER USE CT ONE IN THIS CASE. - EXT_NUM_FOR_R1=.TRUE. -C ------------------------------- - -C The initialization below is for CT v1.8.+ - CALL CTSINIT(THRS,LOOPLIB,EXT_NUM_FOR_R1) -C The initialization below is for the older stable CT v1.7, still -C used for now in the beta release. -C CALL CTSINIT(THRS,LOOPLIB) - - END - - SUBROUTINE ML5_0_LOOP_2_2( LID, W1, W2, M1,MP_M1, M2,MP_M2, C1 - $ ,MP_C1, C2,MP_C2, RANK, LSYMFACT, LMULTIPLIER, AMPLN, RES, - $ STABLE) - USE ALOHA_OBJECT - - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INTEGER MAXLCOUPLINGS - PARAMETER (MAXLCOUPLINGS=4) - INTEGER NLOOPLINE - PARAMETER (NLOOPLINE=2) - INTEGER NWAVEFUNCS - PARAMETER (NWAVEFUNCS=10) - INTEGER NCOMB - PARAMETER (NCOMB=16) -C -C ARGUMENTS -C - INTEGER W1, W2 - COMPLEX*16 M1, M2 - COMPLEX*32 MP_M1, MP_M2 - COMPLEX*16 C1, C2 - COMPLEX*32 MP_C1, MP_C2 - - COMPLEX*16 RES(3) - INTEGER LID, RANK, LSYMFACT, LMULTIPLIER - INTEGER AMPLN - LOGICAL STABLE -C -C LOCAL VARIABLES -C - REAL*8 PL(0:3,NLOOPLINE) - COMPLEX*16 M2L(NLOOPLINE) - INTEGER PAIRING(NLOOPLINE) - INTEGER I, J, K, TEMP -C -C GLOBAL VARIABLES -C - INTEGER WE(NEXTERNAL) - INTEGER ID, SYMFACT, MULTIPLIER, AMPLNUM - COMMON/ML5_0_LOOP/WE,ID, SYMFACT, MULTIPLIER,AMPLNUM - - COMPLEX*16 LC(MAXLCOUPLINGS) - COMPLEX*16 ML(NEXTERNAL+2) - COMMON/ML5_0_DP_LOOP/LC,ML - - COMPLEX*32 MP_LC(MAXLCOUPLINGS) - COMPLEX*32 MP_ML(NEXTERNAL+2) - COMMON/ML5_0_MP_LOOP/MP_LC,MP_ML - - TYPE(ALOHA) W(NWAVEFUNCS,NCOMB) - INTEGER VALIDH - COMMON/ML5_0_WFCTS/W - COMMON/ML5_0_VALIDH/VALIDH - -C ---------- -C BEGIN CODE -C ---------- - - WE(1)=W1 - WE(2)=W2 - M2L(1)=M2**2 - M2L(2)=M1**2 - ML(1)=M2 - ML(2)=M2 - MP_ML(1)=MP_M2 - MP_ML(2)=MP_M2 - ML(3)=M1 - MP_ML(3)=MP_M1 - ML(4)=M2 - MP_ML(4)=MP_M2 - DO I=1,NLOOPLINE - PAIRING(I)=1 - ENDDO - - LC(1)=C1 - MP_LC(1)=MP_C1 - LC(2)=C2 - MP_LC(2)=MP_C2 - AMPLNUM=AMPLN - ID=LID - SYMFACT=LSYMFACT - MULTIPLIER=LMULTIPLIER - DO I=0,3 - TEMP=1 - DO J=1,NLOOPLINE - PL(I,J)=0.D0 - DO K=TEMP,(TEMP+PAIRING(J)-1) - PL(I,J)=PL(I,J)-W(WE(K),VALIDH)%P(I) - ENDDO - TEMP=TEMP+PAIRING(J) - ENDDO - ENDDO - CALL ML5_0_CTLOOP(NLOOPLINE,PL,M2L,RANK,RES,STABLE) - - END - - SUBROUTINE ML5_0_LOOP_3_3( LID, W1, W2, W3, M1,MP_M1, M2,MP_M2, - $ M3,MP_M3, C1,MP_C1, C2,MP_C2, C3,MP_C3, RANK, LSYMFACT, - $ LMULTIPLIER, AMPLN, RES, STABLE) - USE ALOHA_OBJECT - - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INTEGER MAXLCOUPLINGS - PARAMETER (MAXLCOUPLINGS=4) - INTEGER NLOOPLINE - PARAMETER (NLOOPLINE=3) - INTEGER NWAVEFUNCS - PARAMETER (NWAVEFUNCS=10) - INTEGER NCOMB - PARAMETER (NCOMB=16) -C -C ARGUMENTS -C - INTEGER W1, W2, W3 - COMPLEX*16 M1, M2, M3 - COMPLEX*32 MP_M1, MP_M2, MP_M3 - COMPLEX*16 C1, C2, C3 - COMPLEX*32 MP_C1, MP_C2, MP_C3 - - COMPLEX*16 RES(3) - INTEGER LID, RANK, LSYMFACT, LMULTIPLIER - INTEGER AMPLN - LOGICAL STABLE -C -C LOCAL VARIABLES -C - REAL*8 PL(0:3,NLOOPLINE) - COMPLEX*16 M2L(NLOOPLINE) - INTEGER PAIRING(NLOOPLINE) - INTEGER I, J, K, TEMP -C -C GLOBAL VARIABLES -C - INTEGER WE(NEXTERNAL) - INTEGER ID, SYMFACT, MULTIPLIER, AMPLNUM - COMMON/ML5_0_LOOP/WE,ID, SYMFACT, MULTIPLIER,AMPLNUM - - COMPLEX*16 LC(MAXLCOUPLINGS) - COMPLEX*16 ML(NEXTERNAL+2) - COMMON/ML5_0_DP_LOOP/LC,ML - - COMPLEX*32 MP_LC(MAXLCOUPLINGS) - COMPLEX*32 MP_ML(NEXTERNAL+2) - COMMON/ML5_0_MP_LOOP/MP_LC,MP_ML - - TYPE(ALOHA) W(NWAVEFUNCS,NCOMB) - INTEGER VALIDH - COMMON/ML5_0_WFCTS/W - COMMON/ML5_0_VALIDH/VALIDH - -C ---------- -C BEGIN CODE -C ---------- - - WE(1)=W1 - WE(2)=W2 - WE(3)=W3 - M2L(1)=M3**2 - M2L(2)=M1**2 - M2L(3)=M2**2 - ML(1)=M3 - ML(2)=M3 - MP_ML(1)=MP_M3 - MP_ML(2)=MP_M3 - ML(3)=M1 - MP_ML(3)=MP_M1 - ML(4)=M2 - MP_ML(4)=MP_M2 - ML(5)=M3 - MP_ML(5)=MP_M3 - DO I=1,NLOOPLINE - PAIRING(I)=1 - ENDDO - - LC(1)=C1 - MP_LC(1)=MP_C1 - LC(2)=C2 - MP_LC(2)=MP_C2 - LC(3)=C3 - MP_LC(3)=MP_C3 - AMPLNUM=AMPLN - ID=LID - SYMFACT=LSYMFACT - MULTIPLIER=LMULTIPLIER - DO I=0,3 - TEMP=1 - DO J=1,NLOOPLINE - PL(I,J)=0.D0 - DO K=TEMP,(TEMP+PAIRING(J)-1) - PL(I,J)=PL(I,J)-W(WE(K),VALIDH)%P(I) - ENDDO - TEMP=TEMP+PAIRING(J) - ENDDO - ENDDO - CALL ML5_0_CTLOOP(NLOOPLINE,PL,M2L,RANK,RES,STABLE) - - END - - SUBROUTINE ML5_0_LOOP_4_4( LID, W1, W2, W3, W4, M1,MP_M1, M2 - $ ,MP_M2, M3,MP_M3, M4,MP_M4, C1,MP_C1, C2,MP_C2, C3,MP_C3, C4 - $ ,MP_C4, RANK, LSYMFACT, LMULTIPLIER, AMPLN, RES, STABLE) - USE ALOHA_OBJECT - - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INTEGER MAXLCOUPLINGS - PARAMETER (MAXLCOUPLINGS=4) - INTEGER NLOOPLINE - PARAMETER (NLOOPLINE=4) - INTEGER NWAVEFUNCS - PARAMETER (NWAVEFUNCS=10) - INTEGER NCOMB - PARAMETER (NCOMB=16) -C -C ARGUMENTS -C - INTEGER W1, W2, W3, W4 - COMPLEX*16 M1, M2, M3, M4 - COMPLEX*32 MP_M1, MP_M2, MP_M3, MP_M4 - COMPLEX*16 C1, C2, C3, C4 - COMPLEX*32 MP_C1, MP_C2, MP_C3, MP_C4 - - COMPLEX*16 RES(3) - INTEGER LID, RANK, LSYMFACT, LMULTIPLIER - INTEGER AMPLN - LOGICAL STABLE -C -C LOCAL VARIABLES -C - REAL*8 PL(0:3,NLOOPLINE) - COMPLEX*16 M2L(NLOOPLINE) - INTEGER PAIRING(NLOOPLINE) - INTEGER I, J, K, TEMP -C -C GLOBAL VARIABLES -C - INTEGER WE(NEXTERNAL) - INTEGER ID, SYMFACT, MULTIPLIER, AMPLNUM - COMMON/ML5_0_LOOP/WE,ID, SYMFACT, MULTIPLIER,AMPLNUM - - COMPLEX*16 LC(MAXLCOUPLINGS) - COMPLEX*16 ML(NEXTERNAL+2) - COMMON/ML5_0_DP_LOOP/LC,ML - - COMPLEX*32 MP_LC(MAXLCOUPLINGS) - COMPLEX*32 MP_ML(NEXTERNAL+2) - COMMON/ML5_0_MP_LOOP/MP_LC,MP_ML - - TYPE(ALOHA) W(NWAVEFUNCS,NCOMB) - INTEGER VALIDH - COMMON/ML5_0_WFCTS/W - COMMON/ML5_0_VALIDH/VALIDH - -C ---------- -C BEGIN CODE -C ---------- - - WE(1)=W1 - WE(2)=W2 - WE(3)=W3 - WE(4)=W4 - M2L(1)=M4**2 - M2L(2)=M1**2 - M2L(3)=M2**2 - M2L(4)=M3**2 - ML(1)=M4 - ML(2)=M4 - MP_ML(1)=MP_M4 - MP_ML(2)=MP_M4 - ML(3)=M1 - MP_ML(3)=MP_M1 - ML(4)=M2 - MP_ML(4)=MP_M2 - ML(5)=M3 - MP_ML(5)=MP_M3 - ML(6)=M4 - MP_ML(6)=MP_M4 - DO I=1,NLOOPLINE - PAIRING(I)=1 - ENDDO - - LC(1)=C1 - MP_LC(1)=MP_C1 - LC(2)=C2 - MP_LC(2)=MP_C2 - LC(3)=C3 - MP_LC(3)=MP_C3 - LC(4)=C4 - MP_LC(4)=MP_C4 - AMPLNUM=AMPLN - ID=LID - SYMFACT=LSYMFACT - MULTIPLIER=LMULTIPLIER - DO I=0,3 - TEMP=1 - DO J=1,NLOOPLINE - PL(I,J)=0.D0 - DO K=TEMP,(TEMP+PAIRING(J)-1) - PL(I,J)=PL(I,J)-W(WE(K),VALIDH)%P(I) - ENDDO - TEMP=TEMP+PAIRING(J) - ENDDO - ENDDO - CALL ML5_0_CTLOOP(NLOOPLINE,PL,M2L,RANK,RES,STABLE) - - END - - SUBROUTINE ML5_0_LOOP_2_3_2( LID, P1, P2, W1, W2, W3, M1,MP_M1, - $ M2,MP_M2, C1,MP_C1, C2,MP_C2, RANK, LSYMFACT, LMULTIPLIER, - $ AMPLN, RES, STABLE) - USE ALOHA_OBJECT - - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INTEGER MAXLCOUPLINGS - PARAMETER (MAXLCOUPLINGS=4) - INTEGER NLOOPLINE - PARAMETER (NLOOPLINE=2) - INTEGER NWAVEFUNCS - PARAMETER (NWAVEFUNCS=10) - INTEGER NCOMB - PARAMETER (NCOMB=16) -C -C ARGUMENTS -C - INTEGER W1, W2, W3 - COMPLEX*16 M1, M2 - COMPLEX*32 MP_M1, MP_M2 - COMPLEX*16 C1, C2 - COMPLEX*32 MP_C1, MP_C2 - INTEGER P1, P2 - COMPLEX*16 RES(3) - INTEGER LID, RANK, LSYMFACT, LMULTIPLIER - INTEGER AMPLN - LOGICAL STABLE -C -C LOCAL VARIABLES -C - REAL*8 PL(0:3,NLOOPLINE) - COMPLEX*16 M2L(NLOOPLINE) - INTEGER PAIRING(NLOOPLINE) - INTEGER I, J, K, TEMP -C -C GLOBAL VARIABLES -C - INTEGER WE(NEXTERNAL) - INTEGER ID, SYMFACT, MULTIPLIER, AMPLNUM - COMMON/ML5_0_LOOP/WE,ID, SYMFACT, MULTIPLIER,AMPLNUM - - COMPLEX*16 LC(MAXLCOUPLINGS) - COMPLEX*16 ML(NEXTERNAL+2) - COMMON/ML5_0_DP_LOOP/LC,ML - - COMPLEX*32 MP_LC(MAXLCOUPLINGS) - COMPLEX*32 MP_ML(NEXTERNAL+2) - COMMON/ML5_0_MP_LOOP/MP_LC,MP_ML - - TYPE(ALOHA) W(NWAVEFUNCS,NCOMB) - INTEGER VALIDH - COMMON/ML5_0_WFCTS/W - COMMON/ML5_0_VALIDH/VALIDH - -C ---------- -C BEGIN CODE -C ---------- - - WE(1)=W1 - WE(2)=W2 - WE(3)=W3 - M2L(1)=M2**2 - M2L(2)=M1**2 - ML(1)=M2 - ML(2)=M2 - MP_ML(1)=MP_M2 - MP_ML(2)=MP_M2 - ML(3)=M1 - MP_ML(3)=MP_M1 - ML(4)=M2 - MP_ML(4)=MP_M2 - PAIRING(1)=P1 - PAIRING(2)=P2 - LC(1)=C1 - MP_LC(1)=MP_C1 - LC(2)=C2 - MP_LC(2)=MP_C2 - AMPLNUM=AMPLN - ID=LID - SYMFACT=LSYMFACT - MULTIPLIER=LMULTIPLIER - DO I=0,3 - TEMP=1 - DO J=1,NLOOPLINE - PL(I,J)=0.D0 - DO K=TEMP,(TEMP+PAIRING(J)-1) - PL(I,J)=PL(I,J)-W(WE(K),VALIDH)%P(I) - ENDDO - TEMP=TEMP+PAIRING(J) - ENDDO - ENDDO - CALL ML5_0_CTLOOP(NLOOPLINE,PL,M2L,RANK,RES,STABLE) - - END - - SUBROUTINE ML5_0_LOOP_3_4_3( LID, P1, P2, P3, W1, W2, W3, W4, M1 - $ ,MP_M1, M2,MP_M2, M3,MP_M3, C1,MP_C1, C2,MP_C2, C3,MP_C3, RANK - $ , LSYMFACT, LMULTIPLIER, AMPLN, RES, STABLE) - USE ALOHA_OBJECT - - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INTEGER MAXLCOUPLINGS - PARAMETER (MAXLCOUPLINGS=4) - INTEGER NLOOPLINE - PARAMETER (NLOOPLINE=3) - INTEGER NWAVEFUNCS - PARAMETER (NWAVEFUNCS=10) - INTEGER NCOMB - PARAMETER (NCOMB=16) -C -C ARGUMENTS -C - INTEGER W1, W2, W3, W4 - COMPLEX*16 M1, M2, M3 - COMPLEX*32 MP_M1, MP_M2, MP_M3 - COMPLEX*16 C1, C2, C3 - COMPLEX*32 MP_C1, MP_C2, MP_C3 - INTEGER P1, P2, P3 - COMPLEX*16 RES(3) - INTEGER LID, RANK, LSYMFACT, LMULTIPLIER - INTEGER AMPLN - LOGICAL STABLE -C -C LOCAL VARIABLES -C - REAL*8 PL(0:3,NLOOPLINE) - COMPLEX*16 M2L(NLOOPLINE) - INTEGER PAIRING(NLOOPLINE) - INTEGER I, J, K, TEMP -C -C GLOBAL VARIABLES -C - INTEGER WE(NEXTERNAL) - INTEGER ID, SYMFACT, MULTIPLIER, AMPLNUM - COMMON/ML5_0_LOOP/WE,ID, SYMFACT, MULTIPLIER,AMPLNUM - - COMPLEX*16 LC(MAXLCOUPLINGS) - COMPLEX*16 ML(NEXTERNAL+2) - COMMON/ML5_0_DP_LOOP/LC,ML - - COMPLEX*32 MP_LC(MAXLCOUPLINGS) - COMPLEX*32 MP_ML(NEXTERNAL+2) - COMMON/ML5_0_MP_LOOP/MP_LC,MP_ML - - TYPE(ALOHA) W(NWAVEFUNCS,NCOMB) - INTEGER VALIDH - COMMON/ML5_0_WFCTS/W - COMMON/ML5_0_VALIDH/VALIDH - -C ---------- -C BEGIN CODE -C ---------- - - WE(1)=W1 - WE(2)=W2 - WE(3)=W3 - WE(4)=W4 - M2L(1)=M3**2 - M2L(2)=M1**2 - M2L(3)=M2**2 - ML(1)=M3 - ML(2)=M3 - MP_ML(1)=MP_M3 - MP_ML(2)=MP_M3 - ML(3)=M1 - MP_ML(3)=MP_M1 - ML(4)=M2 - MP_ML(4)=MP_M2 - ML(5)=M3 - MP_ML(5)=MP_M3 - PAIRING(1)=P1 - PAIRING(2)=P2 - PAIRING(3)=P3 - LC(1)=C1 - MP_LC(1)=MP_C1 - LC(2)=C2 - MP_LC(2)=MP_C2 - LC(3)=C3 - MP_LC(3)=MP_C3 - AMPLNUM=AMPLN - ID=LID - SYMFACT=LSYMFACT - MULTIPLIER=LMULTIPLIER - DO I=0,3 - TEMP=1 - DO J=1,NLOOPLINE - PL(I,J)=0.D0 - DO K=TEMP,(TEMP+PAIRING(J)-1) - PL(I,J)=PL(I,J)-W(WE(K),VALIDH)%P(I) - ENDDO - TEMP=TEMP+PAIRING(J) - ENDDO - ENDDO - CALL ML5_0_CTLOOP(NLOOPLINE,PL,M2L,RANK,RES,STABLE) - - END - diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoop5_resources b/UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoop5_resources deleted file mode 120000 index 6a87da9776..0000000000 --- a/UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoop5_resources +++ /dev/null @@ -1 +0,0 @@ -../MadLoop5_resources \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoopCommons.f b/UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoopCommons.f deleted file mode 120000 index 836e6d22fb..0000000000 --- a/UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoopCommons.f +++ /dev/null @@ -1 +0,0 @@ -../MadLoopCommons.f \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoopParamReader.f b/UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoopParamReader.f deleted file mode 120000 index fed1ffb18b..0000000000 --- a/UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoopParamReader.f +++ /dev/null @@ -1 +0,0 @@ -../MadLoopParamReader.f \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoopParams.inc b/UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoopParams.inc deleted file mode 120000 index 84aae98059..0000000000 --- a/UNITTEST_proc/SubProcesses/P0_gg_ttx/MadLoopParams.inc +++ /dev/null @@ -1 +0,0 @@ -../MadLoopParams.inc \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/born_matrix.f b/UNITTEST_proc/SubProcesses/P0_gg_ttx/born_matrix.f deleted file mode 100644 index b9066b0d2e..0000000000 --- a/UNITTEST_proc/SubProcesses/P0_gg_ttx/born_matrix.f +++ /dev/null @@ -1,989 +0,0 @@ - SUBROUTINE ML5_0_SMATRIXHEL(P,HEL, FLAV_IDX, ANS) - IMPLICIT NONE -C -C CONSTANT -C - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INTEGER NCOMB - PARAMETER ( NCOMB=16) -CF2PY INTENT(OUT) :: ANS -CF2PY INTENT(IN) :: HEL -CF2PY INTENT(IN) :: P(0:3,NEXTERNAL) -CF2PY INTENT(IN) :: FLAV_IDX - -C -C ARGUMENTS -C - REAL*8 P(0:3,NEXTERNAL),ANS - INTEGER HEL - INTEGER FLAV_IDX -C -C GLOBAL VARIABLES -C - INTEGER USERHEL - COMMON/ML5_0_HELUSERCHOICE/USERHEL -C ---------- -C BEGIN CODE -C ---------- - USERHEL=HEL - CALL ML5_0_SMATRIX(P,FLAV_IDX,ANS) - USERHEL=-1 - - END - - SUBROUTINE ML5_0_SMATRIX(P, FLAV_IDX, ANS) -C -C Generated by MadGraph5_aMC@NLO v. 3.7.2, 2026-04-29 -C By the MadGraph5_aMC@NLO Development Team -C Visit launchpad.net/madgraph5 and amcatnlo.web.cern.ch -C -C MadGraph5_aMC@NLO StandAlone Version -C -C Returns amplitude squared summed/avg over colors -C and helicities -C for the point in phase space P(0:3,NEXTERNAL) -C -C Process: g g > t t~ QCD<=2 QED=0 [ virt = QCD ] -C - IMPLICIT NONE -C -C CONSTANTS -C - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INTEGER NINITIAL - PARAMETER (NINITIAL=2) - INTEGER NPOLENTRIES - PARAMETER (NPOLENTRIES=(NEXTERNAL+1)*6) - INTEGER NCOMB - PARAMETER ( NCOMB=16) - INTEGER HELAVGFACTOR - PARAMETER (HELAVGFACTOR=4) -C -C ARGUMENTS -C - REAL*8 P(0:3,NEXTERNAL),ANS -CF2PY INTENT(OUT) :: ANS -CF2PY INTENT(IN) :: P(0:3,NEXTERNAL) -CF2PY INTENT(IN) :: FLAV_IDX -C -C LOCAL VARIABLES -C - INTEGER NHEL(NEXTERNAL,NCOMB) -C put in common block to expose this variable to python interface - COMMON/ML5_0_PROCESS_NHEL/NHEL - REAL*8 T - REAL*8 ML5_0_MATRIX - INTEGER IHEL,IDEN, I, J -C For a 1>N process, them BEAMTWO_HELAVGFACTOR would be set to 1. - INTEGER BEAMS_HELAVGFACTOR(2) - DATA (BEAMS_HELAVGFACTOR(I),I=1,2)/2,2/ - INTEGER FLAVOR(NEXTERNAL) - INTEGER JC(NEXTERNAL) - INTEGER NFLAV - PARAMETER (NFLAV=1) - INTEGER NNTRY_FLAV, NGOODHEL_FLAV - PARAMETER (NNTRY_FLAV=NFLAV) - PARAMETER (NGOODHEL_FLAV=NCOMB*NFLAV) - INTEGER FLAV_IDX - INTEGER ML5_0_GET_FLAVOR_INDEX - INTEGER NTRY(NFLAV) - LOGICAL GOODHEL(NCOMB,NFLAV) - DATA NTRY/NNTRY_FLAV*0/ - DATA GOODHEL/NGOODHEL_FLAV*.FALSE./ - -C -C GLOBAL VARIABLES -C - INTEGER USERHEL - COMMON/ML5_0_HELUSERCHOICE/USERHEL - DATA USERHEL/-1/ - LOGICAL HELRESET - COMMON/ML5_0_HELRESET/HELRESET - DATA HELRESET/.TRUE./ - - DATA (NHEL(I, 1),I=1,4) /-1,-1,-1, 1/ - DATA (NHEL(I, 2),I=1,4) /-1,-1,-1,-1/ - DATA (NHEL(I, 3),I=1,4) /-1,-1, 1, 1/ - DATA (NHEL(I, 4),I=1,4) /-1,-1, 1,-1/ - DATA (NHEL(I, 5),I=1,4) /-1, 1,-1, 1/ - DATA (NHEL(I, 6),I=1,4) /-1, 1,-1,-1/ - DATA (NHEL(I, 7),I=1,4) /-1, 1, 1, 1/ - DATA (NHEL(I, 8),I=1,4) /-1, 1, 1,-1/ - DATA (NHEL(I, 9),I=1,4) / 1,-1,-1, 1/ - DATA (NHEL(I, 10),I=1,4) / 1,-1,-1,-1/ - DATA (NHEL(I, 11),I=1,4) / 1,-1, 1, 1/ - DATA (NHEL(I, 12),I=1,4) / 1,-1, 1,-1/ - DATA (NHEL(I, 13),I=1,4) / 1, 1,-1, 1/ - DATA (NHEL(I, 14),I=1,4) / 1, 1,-1,-1/ - DATA (NHEL(I, 15),I=1,4) / 1, 1, 1, 1/ - DATA (NHEL(I, 16),I=1,4) / 1, 1, 1,-1/ - DATA IDEN/256/ - - INTEGER POLARIZATIONS(0:NEXTERNAL,0:5) - COMMON/ML5_0_BORN_BEAM_POL/POLARIZATIONS - DATA ((POLARIZATIONS(I,J),I=0,NEXTERNAL),J=0,5)/NPOLENTRIES*-1/ - -C -C FUNCTIONS -C - LOGICAL ML5_0_IS_BORN_HEL_SELECTED - INTEGER ML5_0_BROKEN_SYM -C ---------- -C Check if helreset mode is on -C --------- - IF (HELRESET) THEN - DO I=1,NFLAV - NTRY(I) = 0 - ENDDO - DO I=1,NCOMB - DO J=1,NFLAV - GOODHEL(I,J) = .FALSE. - ENDDO - ENDDO - HELRESET = .FALSE. - ENDIF - -C ---------- -C BEGIN CODE -C ---------- -C FLAV_IDX=0 (or out of range) means GET_FLAVOR_INDEX could not -C resolve -C the requested flavor: it is not an allowed combination, so its -C matrix -C element is identically zero. Short-circuit before touching the -C 1..NFLAV GOODHEL/NTRY arrays. - IF (FLAV_IDX.LT.1 .OR. FLAV_IDX.GT.NFLAV) THEN - ANS = 0D0 - RETURN - ENDIF - CALL ML5_0_GET_FLAVOR(FLAV_IDX, FLAVOR) - IF(USERHEL.EQ.-1) NTRY(FLAV_IDX)=NTRY(FLAV_IDX)+1 - DO IHEL=1,NEXTERNAL - JC(IHEL) = +1 - ENDDO -C When spin-2 particles are involved, the Helicity filtering is -C dangerous for the 2->1 topology. -C This is because depending on the MC setup the initial PS points -C have back-to-back initial states -C for which some of the spin-2 helicity configurations are zero. -C But they are no longer zero -C if the point is boosted on the z-axis. Remember that HELAS -C helicity amplitudes are no longer -C lorentz invariant with expternal spin-2 particles (only the -C helicity sum is). -C For this reason, we simply remove the filterin when there is -C only three external particles. - IF (NEXTERNAL.LE.3) THEN - DO IHEL=1,NCOMB - DO J=1,NFLAV - GOODHEL(IHEL,J)=.TRUE. - ENDDO - ENDDO - ENDIF - ANS = 0D0 - DO IHEL=1,NCOMB - IF (USERHEL.EQ.-1.OR.USERHEL.EQ.IHEL) THEN - IF (GOODHEL(IHEL,FLAV_IDX) .OR. NTRY(FLAV_IDX) .LT. - $ 20.OR.USERHEL.NE.-1) THEN - IF(NTRY(FLAV_IDX).GE.2.AND.POLARIZATIONS(0,0).NE. - $ -1.AND.(.NOT.ML5_0_IS_BORN_HEL_SELECTED(IHEL))) THEN - CYCLE - ENDIF - T=ML5_0_MATRIX(P ,NHEL(1,IHEL),JC(1),FLAV_IDX) - IF(POLARIZATIONS(0,0).EQ. - $ -1.OR.ML5_0_IS_BORN_HEL_SELECTED(IHEL)) THEN - ANS=ANS+T - ENDIF - IF (T .NE. 0D0 .AND. .NOT. GOODHEL(IHEL,FLAV_IDX)) THEN - GOODHEL(IHEL,FLAV_IDX)=.TRUE. - ENDIF - ENDIF - ENDIF - ENDDO - ANS=ANS/DBLE(IDEN)*ML5_0_BROKEN_SYM(FLAVOR) - IF(USERHEL.NE.-1) THEN - ANS=ANS*HELAVGFACTOR - ELSE - DO J=1,NINITIAL - IF (POLARIZATIONS(J,0).NE.-1) THEN - ANS=ANS*BEAMS_HELAVGFACTOR(J) - ANS=ANS/POLARIZATIONS(J,0) - ENDIF - ENDDO - ENDIF - END - - - REAL*8 FUNCTION ML5_0_MATRIX(P,NHEL,IC,FLAV_IDX) - USE MODEL_OBJECT -C -C Generated by MadGraph5_aMC@NLO v. 3.7.2, 2026-04-29 -C By the MadGraph5_aMC@NLO Development Team -C Visit launchpad.net/madgraph5 and amcatnlo.web.cern.ch -C -C Returns amplitude squared -- no average over initial -C state/symmetry factor -C for the point with external lines W(0:6,NEXTERNAL) -C -C Process: g g > t t~ QCD<=2 QED=0 [ virt = QCD ] -C - USE ALOHA_OBJECT - IMPLICIT NONE -C -C CONSTANTS -C - INTEGER NGRAPHS - PARAMETER (NGRAPHS=3) - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INTEGER NWAVEFUNCS, NCOLOR - PARAMETER (NWAVEFUNCS=5, NCOLOR=2) - REAL*8 ZERO - PARAMETER (ZERO=0D0) - COMPLEX*16 IMAG1 - PARAMETER (IMAG1=(0D0,1D0)) -C -C ARGUMENTS -C - REAL*8 P(0:3,NEXTERNAL) - INTEGER NHEL(NEXTERNAL), IC(NEXTERNAL) - INTEGER FLAV_IDX -C -C LOCAL VARIABLES -C - INTEGER I,J - COMPLEX*16 ZTEMP - INTEGER CF_INDEX - INTEGER ML5_0_CF(3) - INTEGER ML5_0_DENOM - COMMON /ML5_0_COLOR_MATRIX/ ML5_0_CF,ML5_0_DENOM - COMPLEX*16 AMP(NGRAPHS), JAMP(NCOLOR), TMP_JAMP(0) - TYPE(ALOHA) W(NWAVEFUNCS) - COMPLEX*16 DUM0,DUM1 - DATA DUM0, DUM1/(0D0, 0D0), (1D0, 0D0)/ -C -C GLOBAL VARIABLES -C - INCLUDE 'coupl.inc' - -C COLOR DATA - DATA ML5_0_DENOM/3/ - DATA (ML5_0_CF(I),I= 1, 2) /16,-4/ -C 1 T(1,2,3,4) - DATA (ML5_0_CF(I),I= 3, 3) /16/ -C 1 T(2,1,3,4) -C -C -C ---------- -C BEGIN CODE -C ---------- - CALL ML5_0_GET_AMP(P,NHEL,IC,FLAV_IDX,AMP) -C WRITE (*,*) ' -> AMP = ', AMP - CALL ML5_0_GET_JAMP(AMP,JAMP) -C WRITE (*,*) ' -> JAMP = ', JAMP - CALL ML5_0_GET_MATRIX(JAMP,ML5_0_MATRIX) -C write (*,*) " -> col.ave. |M|^2 for HEL=[", NHEL ,"] = ", -C ML5_0_MATRIX - - - - END - - SUBROUTINE ML5_0_GET_NHEL(IDEN_STAR,NHEL_STAR) -C CONSTANTS -C -CF2PY INTENT(OUT) :: NHEL_STAR -CF2PY INTENT(OUT) :: IDEN_STAR - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INTEGER NCOMB - PARAMETER ( NCOMB=16) - - INTEGER NHEL(NEXTERNAL,NCOMB),NHEL_STAR(NEXTERNAL,NCOMB) - INTEGER IDEN,IDEN_STAR - - DATA (NHEL(I, 1),I=1,4) /-1,-1,-1, 1/ - DATA (NHEL(I, 2),I=1,4) /-1,-1,-1,-1/ - DATA (NHEL(I, 3),I=1,4) /-1,-1, 1, 1/ - DATA (NHEL(I, 4),I=1,4) /-1,-1, 1,-1/ - DATA (NHEL(I, 5),I=1,4) /-1, 1,-1, 1/ - DATA (NHEL(I, 6),I=1,4) /-1, 1,-1,-1/ - DATA (NHEL(I, 7),I=1,4) /-1, 1, 1, 1/ - DATA (NHEL(I, 8),I=1,4) /-1, 1, 1,-1/ - DATA (NHEL(I, 9),I=1,4) / 1,-1,-1, 1/ - DATA (NHEL(I, 10),I=1,4) / 1,-1,-1,-1/ - DATA (NHEL(I, 11),I=1,4) / 1,-1, 1, 1/ - DATA (NHEL(I, 12),I=1,4) / 1,-1, 1,-1/ - DATA (NHEL(I, 13),I=1,4) / 1, 1,-1, 1/ - DATA (NHEL(I, 14),I=1,4) / 1, 1,-1,-1/ - DATA (NHEL(I, 15),I=1,4) / 1, 1, 1, 1/ - DATA (NHEL(I, 16),I=1,4) / 1, 1, 1,-1/ - DATA IDEN/256/ - IDEN_STAR = IDEN - NHEL_STAR = NHEL - END - - SUBROUTINE ML5_0_GET_AMP(P,NHEL,IC,FLAV_IDX,AMP) - USE MODEL_OBJECT -C -C Process: g g > t t~ QCD<=2 QED=0 [ virt = QCD ] -C -CF2PY INTENT(OUT) :: AMP -CF2PY INTENT(IN) :: NHEL -CF2PY INTENT(IN) :: P(0:3,NEXTERNAL) -CF2PY INTENT(IN) :: IC -CF2PY INTENT(IN) :: FLAV_IDX - - USE ALOHA_OBJECT - IMPLICIT NONE -C -C CONSTANTS -C - INTEGER NGRAPHS - PARAMETER (NGRAPHS=3) - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INTEGER NWAVEFUNCS, NCOLOR - PARAMETER (NWAVEFUNCS=5, NCOLOR=2) - REAL*8 ZERO - PARAMETER (ZERO=0D0) -C -C ARGUMENTS -C - REAL*8 P(0:3,NEXTERNAL) - INTEGER NHEL(NEXTERNAL), IC(NEXTERNAL) - INTEGER FLAV_IDX - INTEGER FLAVOR(NEXTERNAL) -C -C LOCAL VARIABLES -C - COMPLEX*16 AMP(NGRAPHS) - TYPE(ALOHA) W(NWAVEFUNCS) - COMPLEX*16 DUM0,DUM1 - DATA DUM0, DUM1/(0D0, 0D0), (1D0, 0D0)/ - DOUBLE PRECISION BWCUTOFF -C Flavor table for the FLAV_IDX -> FLAVOR rebuild. - INTEGER NMASK_FLAV - PARAMETER (NMASK_FLAV=1) - INTEGER MASK_J - INTEGER FLAV_TABLE(NEXTERNAL, NMASK_FLAV) - DATA FLAV_TABLE / 1, 1, 1, 1 / -C -C GLOBAL VARIABLES -C - INCLUDE 'coupl.inc' - -C -C - BWCUTOFF=15 ! use if $ syntax is defined in the process -C Rebuild FLAVOR(NEXTERNAL) from the resolved flavor index. - IF (FLAV_IDX .GE. 1 .AND. FLAV_IDX .LE. NMASK_FLAV) THEN - DO MASK_J = 1, NEXTERNAL - FLAVOR(MASK_J) = FLAV_TABLE(MASK_J, FLAV_IDX) - ENDDO - ELSE - DO MASK_J = 1, NEXTERNAL - FLAVOR(MASK_J) = FLAV_TABLE(MASK_J, 1) - ENDDO - ENDIF - CALL VXXXXX(P(0,1),ZERO,NHEL(1),-1,W(1)) - CALL VXXXXX(P(0,2),ZERO,NHEL(2),-1,W(2)) - CALL OXXXXX(P(0,3),MDL_MT,NHEL(3),+1, FLAVOR(3),W(3)) - CALL IXXXXX(P(0,4),MDL_MT,NHEL(4),-1, FLAVOR(4),W(4)) - CALL VVV1P0_1(W(1),W(2),GC_4,ZERO,ZERO,W(5)) -C Amplitude(s) for diagram number 1 - CALL FFV1_0(W(4),W(3),W(5),GC_5,AMP(1)) - CALL FFV1_1(W(3),W(1),GC_5,MDL_MT,MDL_WT,W(5)) -C Amplitude(s) for diagram number 2 - CALL FFV1_0(W(4),W(5),W(2),GC_5,AMP(2)) - CALL FFV1_2(W(4),W(1),GC_5,MDL_MT,MDL_WT,W(5)) -C Amplitude(s) for diagram number 3 - CALL FFV1_0(W(5),W(3),W(2),GC_5,AMP(3)) - - END - - SUBROUTINE ML5_0_GET_JAMP(AMP,JAMP) -C -C Process: g g > t t~ QCD<=2 QED=0 [ virt = QCD ] -C -CF2PY INTENT(OUT) :: JAMP -CF2PY INTENT(IN) :: AMP - - IMPLICIT NONE -C -C CONSTANTS -C - INTEGER NGRAPHS - PARAMETER (NGRAPHS=3) - INTEGER NCOLOR - PARAMETER ( NCOLOR=2) - COMPLEX*16 IMAG1 - PARAMETER (IMAG1=(0D0,1D0)) - COMPLEX*16 AMP(NGRAPHS), JAMP(NCOLOR), TMP_JAMP(0) - - JAMP(1) = ((0.000000000000000D+00,1.000000000000000D+00))*AMP(1) - $ +(-1.000000000000000D+00)*AMP(2) - JAMP(2) = ((0.000000000000000D+00,-1.000000000000000D+00))*AMP(1) - $ +(-1.000000000000000D+00)*AMP(3) - END - - SUBROUTINE ML5_0_GET_MATRIX(JAMP,MATRIX) -C -C Process: g g > t t~ QCD<=2 QED=0 [ virt = QCD ] -C - IMPLICIT NONE -C -C CONSTANTS -C -CF2PY INTENT(OUT) :: MATRIX -CF2PY INTENT(IN) :: JAMP - - - INTEGER NCOLOR - PARAMETER (NCOLOR=2) - REAL*8 ZERO,MATRIX - PARAMETER (ZERO=0D0) -C - -C LOCAL VARIABLES -C - INTEGER I,J - COMPLEX*16 ZTEMP - - INTEGER CF_INDEX - INTEGER ML5_0_CF(NCOLOR*(NCOLOR+1)/2) - INTEGER ML5_0_DENOM - COMMON /ML5_0_COLOR_MATRIX/ ML5_0_CF,ML5_0_DENOM - COMPLEX*16 JAMP(NCOLOR), TMP_JAMP(0) - COMPLEX*16 DUM0,DUM1 - DATA DUM0, DUM1/(0D0, 0D0), (1D0, 0D0)/ -C - -C COLOR DATA -C - - MATRIX = 0.D0 - CF_INDEX = 0 - DO I = 1, NCOLOR - ZTEMP = (0.D0,0.D0) - DO J = I, NCOLOR - CF_INDEX = CF_INDEX + 1 - ZTEMP = ZTEMP + ML5_0_CF(CF_INDEX)*JAMP(J) - ENDDO - MATRIX = MATRIX+ZTEMP*DCONJG(JAMP(I))/ML5_0_DENOM - ENDDO - END - - - - SUBROUTINE ML5_0_GET_INTER(JAMP_1,JAMP_2, INTER) - -CF2PY INTENT(OUT) :: INTER -CF2PY INTENT(IN) :: JAMP_1 -CF2PY INTENT(IN) :: JAMP_2 - - INTEGER I,J - INTEGER NCOLOR - PARAMETER (NCOLOR=2) - INTEGER CF_INDEX - INTEGER ML5_0_CF(NCOLOR*(NCOLOR+1)/2) - INTEGER ML5_0_DENOM, IDEN - DATA IDEN/256/ - COMMON /ML5_0_COLOR_MATRIX/ ML5_0_CF,ML5_0_DENOM - COMPLEX*16 JAMP_1(NCOLOR),JAMP_2(NCOLOR),INTER - -C COLOR DATA -C - - INTER = (0.D0,0.D0) - CF_INDEX = 0 - DO I = 1, NCOLOR -C ZTEMP = DCONJG(JAMP_2(I)) - DO J=I, NCOLOR - CF_INDEX = CF_INDEX +1 - INTER = INTER + ML5_0_CF(CF_INDEX) * (JAMP_1(J) * - $ DCONJG(JAMP_2(I)) +JAMP_1(I) * DCONJG(JAMP_2(J))) - ENDDO - ENDDO - INTER = INTER/ (2D0*ML5_0_DENOM*IDEN) - - END - - - - SUBROUTINE ML5_0_GET_DENSITY(P, POS, N_CHANGING, ALLOW_HEL, - $ N_COMB, FLAVOR, ALPHAS, SCALE2, INTER) -C P momenta -C NHEL base of helicity that are not changing -C POS(N_CHNGING): position of the changing helicity -C n_changing: number of changing helicity -C ALLOW_HEL(NCOMB, N_CHANGING): combination of helicity to -C consider (all jamp computed) -C INTER(NCOMB*(NCOMB+1)/2): all interference term (not the -C symmetric one) - USE MODEL_OBJECT - IMPLICIT NONE -CF2PY INTENT(IN) :: P(0:3,4) -CF2PY INTENT(IN) :: POS(N_CHANGING) -CF2PY INTENT(IN) :: N_CHANGING -CF2PY INTENT(IN) :: ALLOW_HEL(N_CHANGING*N_COMB) -CF2PY INTENT(IN) :: N_COMB -CF2PY INTENT(IN) :: FLAVOR(4) -CF2PY INTENT(IN) :: ALPHAS -CF2PY INTENT(IN) :: SCALE2 -CF2PY INTENT(OUT) :: INTER(N_COMB*(N_COMB+1)/2) -C SCALE2 is a dummy argument added to have the same syntax as in -C loop-induced -C -C -C ARGUMENTS -C - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - REAL*8 P(0:3,NEXTERNAL) - INTEGER THISNHEL(NEXTERNAL) - INTEGER N_CHANGING, N_COMB - INTEGER POS(*) - INTEGER ALLOW_HEL(*) - INTEGER FLAVOR(NEXTERNAL) - DOUBLE PRECISION ALPHAS, SCALE2 - DOUBLE COMPLEX INTER(*) - INTEGER NINTER - INTEGER NB_NHEL - DOUBLE COMPLEX, ALLOCATABLE :: TMP_INTER(:) - PARAMETER (NB_NHEL=16) -C LOCAL - INTEGER I,IHEL,IPART - DOUBLE PRECISION PI -C - INTEGER NHEL(NEXTERNAL,NB_NHEL) -C put in common block to expose this variable to python interface - COMMON/ML5_0_PROCESS_NHEL/NHEL -C -C include coupling definition to update the value of alphas -C - INCLUDE 'coupl.inc' - - NINTER = N_COMB*(N_COMB+1)/2 - ALLOCATE(TMP_INTER(NINTER)) - TMP_INTER(:) = (0D0, 0D0) - - DO I=1, N_COMB*(N_COMB+1)/2 - INTER(I) = 0 - ENDDO - - IF (ALPHAS.NE.0D0) THEN - PI = 3.141592653589793D0 - G = 2* DSQRT(ALPHAS*PI) - CALL UPDATE_AS_PARAM() - ENDIF - DO IHEL =1, NB_NHEL - THISNHEL(:) = NHEL(:, IHEL) - DO IPART=1,N_CHANGING - IF(THISNHEL(POS(IPART)).NE.ALLOW_HEL(IPART)) GOTO 10 !BYPASS COMPUTATION FOR HELICITY - ENDDO - TMP_INTER(:) = 0 - CALL ML5_0_GET_ALL_INTER(P, THISNHEL, POS, N_CHANGING, - $ ALLOW_HEL, N_COMB, FLAVOR, TMP_INTER) - DO I = 1, N_COMB*(N_COMB+1)/2 - INTER(I) = INTER(I) + TMP_INTER(I) - ENDDO - 10 ENDDO - RETURN - DEALLOCATE(TMP_INTER) - END - - SUBROUTINE ML5_0_GET_ALL_INTER(P, NHEL, POS, N_CHANGING, - $ ALLOW_HEL, N_COMB, FLAVOR, INTER) -C P momenta -C NHEL base of helicity that are not changing -C POS(N_CHNGING): position of the changing helicity -C n_changing: number of changing helicity -C ALLOW_HEL(NCOMB, N_CHANGING): combination of helicity to -C consider (all jamp computed) -C INTER((NCOMB*NCOMB+1)/2: all interference term (not the -C symmetric one) - IMPLICIT NONE -CF2PY INTENT(IN) :: P(0:3,4) -CF2PY INTENT(IN) :: NHEL(4) -CF2PY INTENT(IN) :: POS(N_CHANGING) -CF2PY INTENT(IN) :: N_CHANGING -CF2PY INTENT(IN) :: ALLOW_HEL(N_CHANGING*N_COMB) -CF2PY INTENT(IN) :: N_COMB -CF2PY INTENT(IN) :: FLAVOR(4) -CF2PY INTENT(OUT) :: INTER(NCOMB*(NCOMB+1)/2) -C -C -C ARGUMENTS -C - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - REAL*8 P(0:3,NEXTERNAL) - INTEGER NHEL(NEXTERNAL) - INTEGER N_CHANGING, N_COMB - INTEGER POS(*) - INTEGER ALLOW_HEL(*) - INTEGER FLAVOR(NEXTERNAL) - DOUBLE COMPLEX INTER(*) -C -C Intermediate array -C - INTEGER NGRAPHS - PARAMETER (NGRAPHS=3) - INTEGER NCOLOR - PARAMETER (NCOLOR=2) - INTEGER IC(NEXTERNAL) - - DOUBLE COMPLEX AMP(NGRAPHS) - DOUBLE COMPLEX, ALLOCATABLE, SAVE :: JAMP(:,:) - INTEGER, SAVE :: S_NCOMB = 0 - -C -C LOCAL -C - INTEGER I,J,SOL,N - INTEGER FLAV_IDX - INTEGER ML5_0_GET_FLAVOR_INDEX - - IF (ALLOCATED(JAMP) .AND. S_NCOMB.NE.N_COMB) THEN - DEALLOCATE(JAMP) - ENDIF - - IF (.NOT.ALLOCATED(JAMP)) THEN - S_NCOMB=N_COMB - ALLOCATE(JAMP(NCOLOR, N_COMB)) - ENDIF -C ---------- -C BEGIN CODE -C ---------- - IC(:)=1 - FLAV_IDX = ML5_0_GET_FLAVOR_INDEX(FLAVOR) -C Unresolved flavor (not an allowed combination): the matrix -C element and -C therefore all interference terms are zero. - IF (FLAV_IDX.EQ.0) THEN - DO I = 1, N_COMB*(N_COMB+1)/2 - INTER(I) = (0D0, 0D0) - ENDDO - RETURN - ENDIF - DO I = 1, N_COMB - DO N = 1, N_CHANGING - NHEL(POS(N)) = ALLOW_HEL((I-1)*N_CHANGING+N) - ENDDO - CALL ML5_0_GET_AMP(P,NHEL,IC,FLAV_IDX,AMP) - CALL ML5_0_GET_JAMP(AMP,JAMP(1,I)) - ENDDO - - SOL = 0 - DO I = 1, N_COMB - DO J= I, N_COMB - SOL = SOL +1 - CALL ML5_0_GET_INTER(JAMP(1,I), JAMP(1,J), INTER(SOL)) - ENDDO - ENDDO - - - RETURN - END - - - - - SUBROUTINE ML5_0_GET_VALUE(P, ALPHAS, NHEL, FLAVOR ,ANS) -C f2py interface accepting the full FLAVOR(NEXTERNAL) array -C (back-compat): -C resolve it to FLAV_IDX and forward to GET_value_internal. Use -C GET_value_idx below to pass the flavor index directly. - USE MODEL_OBJECT - IMPLICIT NONE -C -C CONSTANT -C - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) -C -C ARGUMENTS -C - REAL*8 P(0:3,NEXTERNAL),ANS - INTEGER NHEL - DOUBLE PRECISION ALPHAS - INTEGER FLAVOR(NEXTERNAL) - INTEGER FLAV_IDX - INTEGER ML5_0_GET_FLAVOR_INDEX -CF2PY INTENT(OUT) :: ANS -CF2PY INTENT(IN) :: NHEL -CF2PY INTENT(IN) :: P(0:3,NEXTERNAL) -CF2PY INTENT(IN) :: ALPHAS -CF2PY INTENT(IN) :: FLAVOR(NEXTERNAL) -C ROUTINE FOR F2PY to read the benchmark point. - - FLAV_IDX = ML5_0_GET_FLAVOR_INDEX(FLAVOR) - CALL ML5_0_GET_VALUE_INTERNAL(P, ALPHAS, NHEL, FLAV_IDX ,ANS) - RETURN - END - - - SUBROUTINE ML5_0_GET_VALUE_IDX(P, ALPHAS, NHEL, FLAV_IDX ,ANS) -C f2py interface accepting the flavor index directly. - USE MODEL_OBJECT - IMPLICIT NONE -C -C CONSTANT -C - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) -C -C ARGUMENTS -C - REAL*8 P(0:3,NEXTERNAL),ANS - INTEGER NHEL - DOUBLE PRECISION ALPHAS - INTEGER FLAV_IDX -CF2PY INTENT(OUT) :: ANS -CF2PY INTENT(IN) :: NHEL -CF2PY INTENT(IN) :: P(0:3,NEXTERNAL) -CF2PY INTENT(IN) :: ALPHAS -CF2PY INTENT(IN) :: FLAV_IDX - - CALL ML5_0_GET_VALUE_INTERNAL(P, ALPHAS, NHEL, FLAV_IDX ,ANS) - RETURN - END - - - SUBROUTINE ML5_0_GET_VALUE_INTERNAL(P, ALPHAS, NHEL, FLAV_IDX - $ ,ANS) - USE MODEL_OBJECT -C This routine is the real value but can not be in the interface -C due to f2py not knowing how to handle the couplings common block - USE MODEL_OBJECT - IMPLICIT NONE -C -C CONSTANT -C - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) -C -C ARGUMENTS -C - REAL*8 P(0:3,NEXTERNAL),ANS - INTEGER NHEL - DOUBLE PRECISION ALPHAS - REAL*8 PI - INTEGER FLAV_IDX -C ROUTINE FOR F2PY to read the benchmark point. -C the include file with the values of the parameters and masses - INCLUDE 'coupl.inc' - - PI = 3.141592653589793D0 - G = 2* DSQRT(ALPHAS*PI) - CALL UPDATE_AS_PARAM() - IF (NHEL.NE.0) THEN - CALL ML5_0_SMATRIXHEL(P, NHEL, FLAV_IDX, ANS) - ELSE - CALL ML5_0_SMATRIX(P, FLAV_IDX, ANS) - ENDIF - RETURN - END - - SUBROUTINE ML5_0_INITIALISEMODEL(PATH) -C ROUTINE FOR F2PY to read the benchmark point. - IMPLICIT NONE - CHARACTER*512 PATH -CF2PY INTENT(IN) :: PATH - CALL SETPARA(PATH) !first call to setup the paramaters - RETURN - END - - LOGICAL FUNCTION ML5_0_IS_BORN_HEL_SELECTED(HELID) - IMPLICIT NONE -C -C CONSTANTS -C - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INTEGER NCOMB - PARAMETER (NCOMB=16) -C -C ARGUMENTS -C - INTEGER HELID -C -C LOCALS -C - INTEGER I,J - LOGICAL FOUNDIT -C -C GLOBALS -C - INTEGER HELC(NEXTERNAL,NCOMB) - COMMON/ML5_0_PROCESS_NHEL/HELC - - INTEGER POLARIZATIONS(0:NEXTERNAL,0:5) - COMMON/ML5_0_BORN_BEAM_POL/POLARIZATIONS -C ---------- -C BEGIN CODE -C ---------- - - ML5_0_IS_BORN_HEL_SELECTED = .TRUE. - IF (POLARIZATIONS(0,0).EQ.-1) THEN - RETURN - ENDIF - - DO I=1,NEXTERNAL - IF (POLARIZATIONS(I,0).EQ.-1) THEN - CYCLE - ENDIF - FOUNDIT = .FALSE. - DO J=1,POLARIZATIONS(I,0) - IF (HELC(I,HELID).EQ.POLARIZATIONS(I,J)) THEN - FOUNDIT = .TRUE. - EXIT - ENDIF - ENDDO - IF(.NOT.FOUNDIT) THEN - ML5_0_IS_BORN_HEL_SELECTED = .FALSE. - RETURN - ENDIF - ENDDO - - RETURN - END - - - INTEGER FUNCTION ML5_0_BROKEN_SYM(FLAV) - INCLUDE 'nexternal.inc' - INTEGER FLAV(NEXTERNAL) - INTEGER I,J,K,ICOMP - INTEGER N_TOT, OLD_FACTOR, TOTAL_FACTOR - INTEGER NCOMP, NENTRIES - PARAMETER (NCOMP=1) - PARAMETER (NENTRIES=2) - INTEGER COMP_BEG(NCOMP), COMP_END(NCOMP), COMP_OLD(NCOMP) - INTEGER PID_LIST(NENTRIES), PID_WORK(NENTRIES) - INTEGER BLOCK_START(NENTRIES), BLOCK_LEN(NENTRIES) - LOGICAL SAME_BLOCK - DATA COMP_BEG /1/ - DATA COMP_END /2/ - DATA COMP_OLD /1/ - DATA PID_LIST /6,-6/ - DATA BLOCK_START /3,4/ - DATA BLOCK_LEN /1,1/ - - PID_WORK = PID_LIST - TOTAL_FACTOR = 1 - DO ICOMP=1,NCOMP - OLD_FACTOR = COMP_OLD(ICOMP) - IF (COMP_OLD(ICOMP).GT.1) THEN - DO I=COMP_BEG(ICOMP),COMP_END(ICOMP) - IF (PID_WORK(I).EQ.0) CYCLE - N_TOT = 1 - DO J=I+1,COMP_END(ICOMP) - IF (PID_WORK(I).EQ.PID_WORK(J)) THEN - SAME_BLOCK = .TRUE. - IF (BLOCK_LEN(I).NE.BLOCK_LEN(J)) SAME_BLOCK = .FALSE. - DO K=1,BLOCK_LEN(I) - IF (FLAV(BLOCK_START(I)+K-1).NE.FLAV(BLOCK_START(J) - $ +K-1)) THEN - SAME_BLOCK = .FALSE. - ENDIF - ENDDO - IF (SAME_BLOCK) THEN - PID_WORK(J) = 0 - N_TOT = N_TOT + 1 - OLD_FACTOR = OLD_FACTOR/N_TOT - ENDIF - ENDIF - ENDDO - ENDDO - ENDIF - TOTAL_FACTOR = TOTAL_FACTOR*OLD_FACTOR - ENDDO - ML5_0_BROKEN_SYM = TOTAL_FACTOR - RETURN - END - - - - INTEGER FUNCTION ML5_0_GET_FLAVOR_INDEX(FLAVOR) -C Resolve an external FLAVOR(NEXTERNAL) group-position vector to -C its -C 1-based index in the allowed-flavor table (the same ordering -C used by -C compute_flavor_masks / the FLAV_TABLE mask columns). A resolved -C flavor -C returns an index in [1,NFLAV]; a flavor that is NOT in the table -C (i.e. -C not a physical/allowed combination, so its matrix element is -C zero) -C returns 0. Callers MUST treat the 0 sentinel as "not a valid -C flavor" -C and short-circuit to a zero result before indexing the 1..NFLAV -C GOODHEL/NTRY arrays or FLAV_TABLE (there is no reserved 0 slot). -C Computed once per phase-space point and then threaded down to -C MATRIX/GET_AMP and the good-helicity filter. - INCLUDE 'nexternal.inc' - INTEGER NFLAV - PARAMETER (NFLAV=1) - INTEGER FLAVOR(NEXTERNAL) -CF2PY INTENT(IN) :: FLAVOR(NEXTERNAL) -CF2PY INTENT(OUT) :: ML5_0_GET_FLAVOR_INDEX - INTEGER FI_I, FI_J - LOGICAL FI_MATCH - INTEGER FI_TABLE(NEXTERNAL, NFLAV) - DATA FI_TABLE /1, 1, 1, 1/ -C 0 sentinel for an unresolved (not-in-table) flavor (see above). - ML5_0_GET_FLAVOR_INDEX = 0 - DO FI_I = 1, NFLAV - FI_MATCH = .TRUE. - DO FI_J = 1, NEXTERNAL - IF (FLAVOR(FI_J) .NE. FI_TABLE(FI_J, FI_I)) THEN - FI_MATCH = .FALSE. - EXIT - ENDIF - ENDDO - IF (FI_MATCH) THEN - ML5_0_GET_FLAVOR_INDEX = FI_I - RETURN - ENDIF - ENDDO - RETURN - END - - - - SUBROUTINE ML5_0_GET_FLAVOR(FLAV_IDX, FLAVOR) -C Reverse of GET_FLAVOR_INDEX: fill FLAVOR(NEXTERNAL) with the -C per-leg -C group-position vector of the FLAV_IDX-th allowed flavor (same -C table / -C ordering). FLAV_IDX is expected in [1,NFLAV] (GET_FLAVOR_INDEX -C never -C returns 0); the bounds guard below is purely defensive and maps -C any -C out-of-range value to the first flavor. Used by the outer entry -C points -C (SMATRIX, ...) which receive FLAV_IDX but still need the FLAVOR -C array -C (e.g. for BROKEN_SYM). - INCLUDE 'nexternal.inc' - INTEGER NFLAV - PARAMETER (NFLAV=1) - INTEGER FLAV_IDX - INTEGER FLAVOR(NEXTERNAL) -CF2PY INTENT(IN) :: FLAV_IDX -CF2PY INTENT(OUT) :: FLAVOR(NEXTERNAL) - INTEGER FA_I, FA_USE - INTEGER FA_TABLE(NEXTERNAL, NFLAV) - DATA FA_TABLE /1, 1, 1, 1/ - FA_USE = FLAV_IDX - IF (FA_USE .LT. 1 .OR. FA_USE .GT. NFLAV) FA_USE = 1 - DO FA_I = 1, NEXTERNAL - FLAVOR(FA_I) = FA_TABLE(FA_I, FA_USE) - ENDDO - RETURN - END - - diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/born_matrix.ps b/UNITTEST_proc/SubProcesses/P0_gg_ttx/born_matrix.ps deleted file mode 100644 index a36c96a56f059bdb3e2cd4faeb4b57e5c652c2aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13824 zcmeHOS&!q!5q|Gq(Ro;47syKDrNe*$uRT^0BX)e`L=YGpi6aq~M46;^B@8CNJzrII zH=7i>J2Tll81Z07BeJXOKDxSlU;O6VA6~y%7q{8#a5PabUVL7h4(t4|`MfxPqF;v- z{*9A~*7N~@n__j^XNP)O9O~*5{rhb9HmmbhilJ}QO@>!G0NiiBPS?LH)8kgXP%rc{ zyBzlELEq%*rcC#hUYF^+gTB3J3zqzte*MK~-~91U4F8u3Ea>Hz|M=$XH{a-+@8A3l zNZ#mUSA zyedHcP3_D&{ z`R1VSCwi0V``|&}zs5&?m+h)dAb{;Qt@29U7=hc>p%%Y ze?v`H!zU^1w&H0-P)5l@#OqoVEuSUZHsnv??Eua2SV`f=49omLZ)%PC0B|t)#=Maa zD6$c7koDmP40uh1vFeZwY=FsCSWFUcUm#`+Jwc>8-&G((G684asLCjPmmg@tgT5hxiBE5GG@ONj0L{WyW4A8a}T? zS~4z8@hxk7optG3<$^iT4ukR>P$usH305WPo__r~WohWF#1l?O2`k3q-if!g!>iuH zr93c_a|yOdptMG^6hZ1Oxnu}X84`ExfI$}%y+c$18h*MB=z$U$tVvJ&K}m*?8;>9b zP88gYCJ6){+$4S#axSuyR8E1vuD9M48k6i~*zE}x3KIz!g9-B~bUVS~*dQpH6U-$m zB7c&}mSrirEe9isb!H-oM0-ypu_cWv9>{$WZ;#-BI8jK1l<~w5Ot3MF2A>~nsxR0m zy03x_t}d!&dl{3kevSOD%z!wBEAc@7D20UdPY6&tH8LwQ3?5i-^;WHl%6lQ1?J=>P zmSyoy-P?@8c^!3uxuPtNDuC~*GznsfF|jm33Y2>T_+eO*gSiGqgW*zhgwk7!|1RI{ zn#6P57Ikq@_xDYx+dST*G3Z>X7}X|JWJCjN$JeS+B~&P$CaIsm#MU+gxHN(IC7FP) z2bWlgtDU0c?>{=?$fr(Sd7Z&;k6& z-4t;oCZ#8yFc9Tja&1Nh?*a_oeeAvdJcOO|4_S$RA%U#mu|UBJs!3~`-HEaquRHYP za+|FNly!aXn&lmbui>kk+bC-f>dWRP%QpSB4o81E$#eSas-j7MK1&^_0abB(k*j{! z>tpFb^<+raBogFvRXJg`pb5Tq(+{Y!Z;tBY`>Cq*S$di(`&e?7$G2{eDzP+SUD^~P z3gv9#g3zXpCJ3o4_FM4U>f)2{aYUb0R~Kke{KN>oCT-%HV&G{GM`7!7>|Ivwv133h z$>+5;hwR-kr3GMrKdPj`m!%Hk&MYe#8U)P(%=BiDuMth!saEMOMX*>t41pHnuC(xn zG1>@kyJ1jvxDdGZApN$^(rns0)zjW_4wE*cr@iB5%I0+I&r&pGPSf5gX$hP5j$NQ{ z4l1GFm(gAg=K_dg8#4P2)0MY-!flra=A)tZ&a}bYazJSo+dzA#Tzg0U{=W8(@KR;r z_KtQF06*B?scuh5EeMAcUvFI3EbStq1j5y)d6K0e;&{(aua0z zk+AX-z%;7xvW;+w5h>pmiyJXriY!c4Hob77Aht~G8@#4G^8hb?x{m#;tD^Ha?)$5& z4!f#LaksnT*6us5y&PwAmDvrQa3=|TdQ+uuGljsxMkOXtDyp&?8`c-iee0&grgBkY zgg4L}p>4j|@W$<6?xZc#CUfQhOxv)NseTJ4$M?D4`EWFJFGfcyIxf$WZ8 ze_^~%tL^UK61V!Nc_DxPg$4pb(nF^*$-e4UWwJ^z(nA&&A6?vY>*g<0erGV3VV$|$ z8@+6|ajdD2mB*yiit^yI+0zOxn5CK}%YUkf#B{^BUvLGqv!B{uaN!M9S-g!<>$b8? zmR(Ql-bC(k1y^0~rw$fe*^D=3s;Qm*`>Be8d@kcD;*={#P1V(&FGgCdWT>(T#t775~b{zp3?|2uJ6zEpUMJ?D!s75954^54?Ee z)?3N7J*JiXxNTsMF@j6VBWIPPkmm41yue?H=d@=_TXwwu13_{>69w!BXm)%E#0Eo@ zd?<){u23kd27Huqodh_h2&;=FB}t%J&agT^ZWf^Ur+*NQMUjGl7bLI5@~;c-=4gc1 z#(_N=`Cl%$pK~fP?9}FT#2yh*g6KFct?9}0D2S+0MzS!C`HJ6j`^M{dlSOC|?%bRc zhI4aX^cXkqEdQy=Y?l8*X?XchiPJ6rUEvs7{$IrlE)DQ0!E@IaAILvat!nRpKx&o$ zMp|iE5n+c;!i&|$Rn&hY?Y3z;?EqVfdrALIFIEAi+U$e2uzJY_2?!0MInWV?;M|ga z%(9S=FXWhqE$#Ll0Eqm^lg>L%ttM?SqhVgcewdNi(dLG%UEDN-B!n5w0gPPrsX!{YYey%f}=YU(IYmR>Ir^n|D{d3L4JG; zaza8GoOJXQ^jSs+#l9*u^re@iO^eeOb$ta!)Cklv3uM4X2<#j?Qf-TOVv|O_{H}}B zPG}UTjJ;m|{S`zzWtxU~x9koEtFr@tr;pp);;h{12C+ff=Dc;y6V{usG9NCQvk_-^ z@ej&_EqbbtUdzOE1&FF9E&_yUP!2 z4m&JH)Htv0=pX8Im#;d*)kTkgxa@C>U3)-{-(_oDpi<*|J-(n7H=^F$p2_wa`} z6tj~aHpmt-l^Agyj^V|SHEyK@9F;i2(-w=0I%cG+%0X`z^I}k(!e-suQ&gC zdgxDo;&9uCz$utPxfgS41=3g|h!sS0ZtzO3WF)saIPsy;Qsa(b9RMI`3Dy~=`7Oyh z<4W?juq=E^(6@Hrq`3W;#ZH7JLQkh%SxJ1oAf&FXV`?s_0E0J;rv1Z5qJ0}C1Aa+Uod zv<{WK0KTU!a@-KUy8mrZ%o3dd32se~rmY`6jgk>9(B(v0E9|d?qp0T(n?MA`283olDRy&WP8cf<$V^EzX@1;t(9o5iL9V8b{=4~25kMy&M z1e!+k5x95Q8;QedG@4JMCQuA~)Tg-zX0=g)gpoU4?q+ZtlcJk?P7IavE0iq5MZf5Kz4zhJE({wQ# z#gk|@3n#NAisq4Su|BzGeYzNhlVCodV%BuJK$&u^I|lkVpF!p}B{wl@CI$g{sZOHU z_XxBG{2w4tO+C;>52$|m-4{2XhQHO{eR=cg!~x?!VE}CcVG$ql9Z}+mnjjd6?mTF@ zL+vnN8te#&gaV<5^#}n=q34tGqAgm)eFPeR(@`ue0Ea{0gqWb6k_)y-crwI^acQ_n zgQ5{Z1gBu~k@*PbEF$>?QkG-FcS)m#SwN&5MB{p-g)Rk83$dtq3T5~duC*`_@;X|O zAqV{<^!y{9^?(leM~DoB9k>`dOuo&?Q#{om=!tGL?f8cut#ej?6tx_rQ4P{emw>04 zAXxMf@H8VCm{2&qH}2uHE#KpWT*VV1n6Y(Zn6BTr{yb4gyl4eUC_Kiqw)Gkh)1l}f zUbNh!iErqDaQc*d9f*><_^)(8D4Y(OdZ116K%(^}bjc&~oFkCr(FPrG4l00Dsj*a` K%fvgZH~s?}h0xsq diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/check_sa.f b/UNITTEST_proc/SubProcesses/P0_gg_ttx/check_sa.f deleted file mode 100644 index 36955bbc9b..0000000000 --- a/UNITTEST_proc/SubProcesses/P0_gg_ttx/check_sa.f +++ /dev/null @@ -1,746 +0,0 @@ - PROGRAM DRIVER -C ***************************************************************** -C ******** -C THIS IS THE DRIVER FOR CHECKING THE STANDALONE MATRIX ELEMENT. -C IT USES A SIMPLE PHASE SPACE GENERATOR -C ***************************************************************** -C ******** - IMPLICIT NONE -C -C CONSTANTS -C - REAL*8 ZERO - PARAMETER (ZERO=0D0) - - LOGICAL READPS - PARAMETER (READPS = .FALSE.) - - INTEGER NPSPOINTS - PARAMETER (NPSPOINTS = 4) - -C integer nexternal and number particles (incoming+outgoing) in -C the me - INTEGER NEXTERNAL, NINCOMING - PARAMETER (NEXTERNAL=4,NINCOMING=2) - - CHARACTER(512) MADLOOPRESOURCEPATH - -C -C INCLUDE FILES -C -C the include file with the values of the parameters and masses -C - INCLUDE 'coupl.inc' -C particle masses - REAL*8 PMASS(NEXTERNAL) -C integer n_max_cg - INCLUDE 'ngraphs.inc' - INCLUDE 'nsqso_born.inc' - INCLUDE 'nsquaredSO.inc' - -C -C LOCAL -C - INTEGER I,J,K -C four momenta. Energy is the zeroth component. - REAL*8 P(0:3,NEXTERNAL) - INTEGER MATELEM_ARRAY_DIM - REAL*8 , ALLOCATABLE :: MATELEM(:,:) - REAL*8 SQRTS,AO2PI,TOTMASS -C sqrt(s)= center of mass energy - REAL*8 PIN(0:3), POUT(0:3) - CHARACTER*120 BUFF(NEXTERNAL) - INTEGER RETURNCODE, UNITS, TENS, HUNDREDS - INTEGER NSQUAREDSO_LOOP - REAL*8 , ALLOCATABLE :: PREC_FOUND(:) - -C -C GLOBAL VARIABLES -C -C This is from ML code for the list of split orders selected by -C the process definition -C - INTEGER NLOOPCHOSEN - CHARACTER*20 CHOSEN_LOOP_SO_INDICES(NSQUAREDSO) - LOGICAL CHOSEN_LOOP_SO_CONFIGS(NSQUAREDSO) - COMMON/ML5_0_CHOSEN_LOOP_SQSO/CHOSEN_LOOP_SO_CONFIGS - INTEGER NBORNCHOSEN - CHARACTER*20 CHOSEN_BORN_SO_INDICES(NSQSO_BORN) - LOGICAL CHOSEN_BORN_SO_CONFIGS(NSQSO_BORN) - COMMON/ML5_0_CHOSEN_BORN_SQSO/CHOSEN_BORN_SO_CONFIGS - -C -C SAVED VARIABLES -C - LOGICAL INIT - DATA INIT/.TRUE./ - COMMON/INITCHECKSA/INIT -C -C EXTERNAL -C - REAL*8 DOT - EXTERNAL DOT - -C -C BEGIN CODE -C -C - - IF (INIT) THEN - INIT=.FALSE. - CALL ML5_0_GET_ANSWER_DIMENSION(MATELEM_ARRAY_DIM) - ALLOCATE(MATELEM(0:3,0:MATELEM_ARRAY_DIM)) - CALL ML5_0_GET_NSQSO_LOOP(NSQUAREDSO_LOOP) - ALLOCATE(PREC_FOUND(0:NSQUAREDSO_LOOP)) - -C INITIALIZATION CALLS -C -C Call to initialize the values of the couplings, masses and -C widths -C used in the evaluation of the matrix element. The primary -C parameters of the -C models are read from Cards/param_card.dat. The secondary -C parameters are calculated -C in Source/MODEL/couplings.f. The values are stored in common -C blocks that are listed -C in coupl.inc . -C first call to setup the paramaters - CALL SETPARA('param_card.dat') -C set up masses - INCLUDE 'pmass.inc' - - ENDIF - - -C Start by initializing what is the squared split orders indices -C chosen - NLOOPCHOSEN=0 - DO I=1,NSQUAREDSO - IF (CHOSEN_LOOP_SO_CONFIGS(I)) THEN - NLOOPCHOSEN=NLOOPCHOSEN+1 - WRITE(CHOSEN_LOOP_SO_INDICES(NLOOPCHOSEN),'(I3,A2)') I,'L)' - ENDIF - ENDDO - NBORNCHOSEN=0 - DO I=1,NSQSO_BORN - IF (CHOSEN_BORN_SO_CONFIGS(I)) THEN - NBORNCHOSEN=NBORNCHOSEN+1 - WRITE(CHOSEN_BORN_SO_INDICES(NBORNCHOSEN),'(I3,A2)') I,'B)' - ENDIF - ENDDO - - AO2PI=G**2/(8.D0*(3.14159265358979323846D0**2)) - - WRITE(*,*) 'AO2PI=',AO2PI -C Now use a simple multipurpose PS generator (RAMBO) just to get a -C RANDOM set of four momenta of given masses pmass(i) to be used -C to evaluate -C the madgraph matrix-element. -C Alternatevely, here the user can call or set the four momenta at -C his will, see below. -C - IF(NINCOMING.EQ.1) THEN - SQRTS=PMASS(1) - ELSE - TOTMASS = 0.0D0 - DO I=1,NEXTERNAL - TOTMASS = TOTMASS + PMASS(I) - ENDDO -C CMS energy in GEV - SQRTS=MAX(1000D0,2.0D0*TOTMASS) - ENDIF - - CALL PRINTOUT() - - - - DO K=1,NPSPOINTS - - IF(READPS) THEN - OPEN(967, FILE='PS.input', ERR=976, STATUS='OLD', - $ ACTION='READ') - DO I=1,NEXTERNAL - READ(967,*,END=978) P(0,I),P(1,I),P(2,I),P(3,I) - ENDDO - GOTO 978 - 976 CONTINUE - STOP 'Could not read the PS.input phase-space point.' - 978 CONTINUE - CLOSE(967) - ELSE - IF ((NINCOMING.EQ.2).AND.((NEXTERNAL - NINCOMING .EQ.1))) - $ THEN - IF (PMASS(3).EQ.0.0D0) THEN - STOP 'Cannot generate 2>1 kin. config. with m3=0.0d0' - ELSE -C deal with the case of only one particle in the final -C state - P(0,1) = PMASS(3)/2D0 - P(1,1) = 0D0 - P(2,1) = 0D0 - P(3,1) = PMASS(3)/2D0 - IF (PMASS(1).GT.0D0) THEN - P(3,1) = DSQRT(PMASS(3)**2/4D0 - PMASS(1)**2) - ENDIF - P(0,2) = PMASS(3)/2D0 - P(1,2) = 0D0 - P(2,2) = 0D0 - P(3,2) = -PMASS(3)/2D0 - IF (PMASS(2) > 0D0) THEN - P(3,2) = -DSQRT(PMASS(3)**2/4D0 - PMASS(1)**2) - ENDIF - P(0,3) = PMASS(3) - P(1,3) = 0D0 - P(2,3) = 0D0 - P(3,3) = 0D0 - ENDIF - ELSE - CALL GET_MOMENTA(SQRTS,PMASS,P) - ENDIF - ENDIF - - DO I=0,3 - PIN(I)=0.0D0 - DO J=1,NINCOMING - PIN(I)=PIN(I)+P(I,J) - ENDDO - ENDDO - -C In standalone mode, always use sqrt_s as the renormalization -C scale. - SQRTS=DSQRT(DABS(DOT(PIN(0),PIN(0)))) - MU_R=SQRTS - -C Update the couplings with the new MU_R - CALL UPDATE_AS_PARAM() - -C Optionally the user can set where to find the -C MadLoop5_resources folder. -C Otherwise it will look for it automatically and find it if it -C has not -C been moved -C MadLoopResourcePath = '' -C CALL SETMADLOOPPATH(MadLoopResourcePath) -C To force the stabiliy check to also be performed in the -C initialization phase -C CALL ML5_0_FORCE_STABILITY_CHECK(.TRUE.) -C To chose a particular tartget split order, SOTARGET is an -C integer labeling -C the possible squared order couplings contributions (only in -C optimized mode) -C CALL ML5_0_SET_COUPLINGORDERS_TARGET(SOTARGET) - - -C -C Now we can call the matrix element -C - CALL ML5_0_SLOOPMATRIX_THRES(P,MATELEM,-1.0D0,PREC_FOUND - $ ,RETURNCODE) - -C -C write the information on the four momenta -C - IF (K.EQ.NPSPOINTS) THEN - WRITE (*,*) - WRITE (*,*) ' Phase space point:' - WRITE (*,*) - WRITE (*,*) '---------------------------------' - WRITE (*,*) 'n E px py pz m' - DO I=1,NEXTERNAL - WRITE (*,'(i2,1x,5e15.7)') I, P(0,I),P(1,I),P(2,I),P(3,I) - $ ,DSQRT(DABS(DOT(P(0,I),P(0,I)))) - ENDDO - WRITE (*,*) '---------------------------------' - WRITE (*,*) 'Detailed result for each coupling orders' - $ //' combination.' - - - UNITS=MOD(RETURNCODE,10) - TENS=(MOD(RETURNCODE,100)-UNITS)/10 - HUNDREDS=(RETURNCODE-TENS*10-UNITS)/100 - IF (HUNDREDS.EQ.1) THEN - IF (TENS.EQ.3.OR.TENS.EQ.4) THEN - WRITE(*,*) 'Unknown numerical stability because MadLoop' - $ //' is in the initialization stage.' - ELSE - WRITE(*,*) 'Unknown numerical stability, check CTModeRun' - $ //' value in MadLoopParams.dat.' - ENDIF - ELSEIF (HUNDREDS.EQ.2) THEN - WRITE(*,*) 'Stable kinematic configuration (SPS).' - ELSEIF (HUNDREDS.EQ.3) THEN - WRITE(*,*) 'Unstable kinematic configuration (UPS).' - WRITE(*,*) 'Quadruple precision rescue successful.' - ELSEIF (HUNDREDS.EQ.4) THEN - WRITE(*,*) 'Exceptional kinematic configuration (EPS).' - WRITE(*,*) 'Both double an quadruple precision' - $ //' computations, are unstable.' - ENDIF - IF (TENS.EQ.2.OR.TENS.EQ.4) THEN - WRITE(*,*) 'Quadruple precision computation used.' - ENDIF - IF (HUNDREDS.NE.1) THEN - IF (PREC_FOUND(0).GT.0.0D0) THEN - WRITE(*,'(1x,a23,1x,1e10.2)') 'Relative accuracy =' - $ ,PREC_FOUND(0) - ELSEIF (PREC_FOUND(0).EQ.0.0D0) THEN - WRITE(*,'(1x,a23,1x,1e10.2,1x,a30)') 'Relative accuracy ' - $ //' =',PREC_FOUND(0),'(i.e. beyond double precision)' - ELSE - WRITE(*,*) 'Estimated accuracy could not be computed for' - $ //' an unknown reason.' - ENDIF - ENDIF - WRITE (*,'(1x,a23,3x,i3)') 'MadLoop return code =' - $ ,RETURNCODE - WRITE (*,*) '---------------------------------' - IF (NBORNCHOSEN.EQ.0) THEN - WRITE (*,*) 'No Born contribution satisfied the squared' - $ //' order constraints.' - ELSE IF (NBORNCHOSEN.NE.NSQSO_BORN) THEN - WRITE (*,*) 'Selected squared coupling orders combination' - $ //' for the Born summed result below:' - WRITE (*,*) (CHOSEN_BORN_SO_INDICES(I),I=1,NBORNCHOSEN) - ENDIF - IF (NLOOPCHOSEN.NE.NSQUAREDSO) THEN - WRITE (*,*) 'Selected squared coupling orders combination' - $ //' for the loop summed result below:' - WRITE (*,*) (CHOSEN_LOOP_SO_INDICES(I),I=1,NLOOPCHOSEN) - ENDIF - WRITE (*,*) '---------------------------------' - WRITE (*,*) 'Matrix element born = ', MATELEM(0,0), - $ ' GeV^',-(2*NEXTERNAL-8) - WRITE (*,*) 'Matrix element finite = ', MATELEM(1,0), - $ ' GeV^',-(2*NEXTERNAL-8) - WRITE (*,*) 'Matrix element 1eps = ', MATELEM(2,0), - $ ' GeV^',-(2*NEXTERNAL-8) - WRITE (*,*) 'Matrix element 2eps = ', MATELEM(3,0), - $ ' GeV^',-(2*NEXTERNAL-8) - WRITE (*,*) '---------------------------------' - IF (MATELEM(0,0).NE.0.0D0) THEN - WRITE (*,*) 'finite / (born*ao2pi) = ', MATELEM(1,0) - $ /MATELEM(0,0)/AO2PI - WRITE (*,*) '1eps / (born*ao2pi) = ', MATELEM(2,0) - $ /MATELEM(0,0)/AO2PI - WRITE (*,*) '2eps / (born*ao2pi) = ', MATELEM(3,0) - $ /MATELEM(0,0)/AO2PI - ELSE - WRITE (*,*) 'finite / ao2pi = ', MATELEM(1,0)/AO2PI - WRITE (*,*) '1eps / ao2pi = ', MATELEM(2,0)/AO2PI - WRITE (*,*) '2eps / ao2pi = ', MATELEM(3,0)/AO2PI - ENDIF - WRITE (*,*) '---------------------------------' - - OPEN(69, FILE='result.dat', ERR=976, ACTION='WRITE') - DO I=1,NEXTERNAL - WRITE (69,'(a2,1x,5ES30.15E3)') 'PS',P(0,I),P(1,I),P(2,I) - $ ,P(3,I) - ENDDO - WRITE (69,'(a3,1x,i3)') 'EXP',-(2*NEXTERNAL-8) - WRITE (69,'(a4,1x,1ES30.15E3)') 'BORN',MATELEM(0,0) - IF (MATELEM(0,0).NE.0.0D0) THEN - WRITE (69,'(a3,1x,1ES30.15E3)') 'FIN',MATELEM(1,0) - $ /MATELEM(0,0)/AO2PI - WRITE (69,'(a4,1x,1ES30.15E3)') '1EPS',MATELEM(2,0) - $ /MATELEM(0,0)/AO2PI - WRITE (69,'(a4,1x,1ES30.15E3)') '2EPS',MATELEM(3,0) - $ /MATELEM(0,0)/AO2PI - ELSE - WRITE (69,'(a3,1x,1ES30.15E3)') 'FIN',MATELEM(1,0)/AO2PI - WRITE (69,'(a4,1x,1ES30.15E3)') '1EPS',MATELEM(2,0)/AO2PI - WRITE (69,'(a4,1x,1ES30.15E3)') '2EPS',MATELEM(3,0)/AO2PI - ENDIF - WRITE (69,'(a6,1x,1ES30.15E3)') 'ASO2PI',AO2PI - WRITE (69,*) 'Export_Format Default' - WRITE (69,'(a7,1x,i3)') 'RETCODE',RETURNCODE - WRITE (69,'(a3,1x,1e10.4)') 'ACC',PREC_FOUND(0) - WRITE (69,*) 'Born_kept',(CHOSEN_BORN_SO_CONFIGS(I),I=1 - $ ,NSQSO_BORN) - WRITE (69,*) 'Loop_kept',(CHOSEN_LOOP_SO_CONFIGS(I),I=1 - $ ,NSQUAREDSO) - - - CLOSE(69) - ELSE - WRITE (*,*) 'PS Point #',K,' done.' - ENDIF - ENDDO - -C C -C C Copy down here (or read in) the four momenta as a string. -C C -C C -C buff(1)=" 1 0.5630480E+04 0.0000000E+00 0.0000000E+00 -C 0.5630480E+04" -C buff(2)=" 2 0.5630480E+04 0.0000000E+00 0.0000000E+00 -C -0.5630480E+04" -C buff(3)=" 3 0.5466073E+04 0.4443190E+03 0.2446331E+04 -C -0.4864732E+04" -C buff(4)=" 4 0.8785819E+03 -0.2533886E+03 0.2741971E+03 -C 0.7759741E+03" -C buff(5)=" 5 0.4916306E+04 -0.1909305E+03 -0.2720528E+04 -C 0.4088757E+04" -C C -C C Here the k,E,px,py,pz are read from the string into the -C momenta array. -C C k=1,2 : incoming -C C k=3,nexternal : outgoing -C C -C do i=1,nexternal -C read (buff(i),*) k, P(0,i),P(1,i),P(2,i),P(3,i) -C enddo -C -C C print the momenta out -C -C do i=1,nexternal -C write (*,'(i2,1x,5e15.7)') i, P(0,i),P(1,i),P(2,i),P(3,i), -C &dsqrt(dabs(DOT(p(0,i),p(0,i)))) -C enddo -C -C CALL SLOOPMATRIX(P,MATELEM) -C -C write (*,*) "-------------------------------------------------" -C write (*,*) "Matrix element = ", MATELEM(1), " -C GeV^",-(2*nexternal-8) -C write (*,*) "-------------------------------------------------" - - DEALLOCATE(MATELEM) - DEALLOCATE(PREC_FOUND) - - END - - - - - DOUBLE PRECISION FUNCTION DOT(P1,P2) -C ************************************************************* -C 4-Vector Dot product -C ************************************************************* - IMPLICIT NONE - DOUBLE PRECISION P1(0:3),P2(0:3) - DOT=P1(0)*P2(0)-P1(1)*P2(1)-P1(2)*P2(2)-P1(3)*P2(3) - END - - - SUBROUTINE GET_MOMENTA(ENERGY,PMASS,P) -C auxiliary function to change convention between madgraph and -C rambo -C four momenta. - IMPLICIT NONE - INTEGER NEXTERNAL, NINCOMING - PARAMETER (NEXTERNAL=4,NINCOMING=2) -C ARGUMENTS - REAL*8 ENERGY,PMASS(NEXTERNAL),P(0:3,NEXTERNAL),PRAMBO(4,10),WGT -C LOCAL - INTEGER I - REAL*8 ETOT2,MOM,M1,M2,E1,E2 - - ETOT2=ENERGY**2 - M1=PMASS(1) - M2=PMASS(2) - MOM=(ETOT2**2 - 2*ETOT2*M1**2 + M1**4 - 2*ETOT2*M2**2 - 2*M1**2 - $ *M2**2 + M2**4)/(4.*ETOT2) - MOM=DSQRT(MOM) - E1=DSQRT(MOM**2+M1**2) - E2=DSQRT(MOM**2+M2**2) -C write (*,*) e1+e2,mom - - IF(NINCOMING.EQ.2) THEN - - P(0,1)=E1 - P(1,1)=0D0 - P(2,1)=0D0 - P(3,1)=MOM - - P(0,2)=E2 - P(1,2)=0D0 - P(2,2)=0D0 - P(3,2)=-MOM - - CALL RAMBO(NEXTERNAL-2,ENERGY,PMASS(NINCOMING+1),PRAMBO,WGT) - DO I=3, NEXTERNAL - P(0,I)=PRAMBO(4,I-2) - P(1,I)=PRAMBO(1,I-2) - P(2,I)=PRAMBO(2,I-2) - P(3,I)=PRAMBO(3,I-2) - ENDDO - - ELSEIF(NINCOMING.EQ.1) THEN - - P(0,1)=ENERGY - P(1,1)=0D0 - P(2,1)=0D0 - P(3,1)=0D0 - - CALL RAMBO(NEXTERNAL-1,ENERGY,PMASS(2),PRAMBO,WGT) - DO I=2, NEXTERNAL - P(0,I)=PRAMBO(4,I-1) - P(1,I)=PRAMBO(1,I-1) - P(2,I)=PRAMBO(2,I-1) - P(3,I)=PRAMBO(3,I-1) - ENDDO - ENDIF - - RETURN - END - - - SUBROUTINE RAMBO(N,ET,XM,P,WT) -C ***************************************************************** -C ***** -C RAMBO * -C RA(NDOM) M(OMENTA) B(EAUTIFULLY) O(RGANIZED) -C * -C * -C A DEMOCRATIC MULTI-PARTICLE PHASE SPACE GENERATOR -C * -C AUTHORS: S.D. ELLIS, R. KLEISS, W.J. STIRLING -C * -C THIS IS VERSION 1.0 - WRITTEN BY R. KLEISS -C * -C -- ADJUSTED BY HANS KUIJF, WEIGHTS ARE LOGARITHMIC (20-08-90) -C * -C * -C N = NUMBER OF PARTICLES -C * -C ET = TOTAL CENTRE-OF-MASS ENERGY -C * -C XM = PARTICLE MASSES ( DIM=NEXTERNAL-nincoming ) -C * -C P = PARTICLE MOMENTA ( DIM=(4,NEXTERNAL-nincoming) ) -C * -C WT = WEIGHT OF THE EVENT -C * -C ***************************************************************** -C ***** - IMPLICIT REAL*8(A-H,O-Z) - INTEGER NEXTERNAL, NINCOMING - PARAMETER (NEXTERNAL=4,NINCOMING=2) - DIMENSION XM(NEXTERNAL-NINCOMING),P(4,NEXTERNAL-NINCOMING) - DIMENSION Q(4,NEXTERNAL-NINCOMING),Z(NEXTERNAL-NINCOMING),R(4) - $ ,B(3),P2(NEXTERNAL-NINCOMING),XM2(NEXTERNAL-NINCOMING) - $ ,E(NEXTERNAL-NINCOMING),V(NEXTERNAL-NINCOMING),IWARN(5) - SAVE ACC,ITMAX,IBEGIN,IWARN - DATA ACC/1.D-14/,ITMAX/6/,IBEGIN/0/,IWARN/5*0/ -C -C INITIALIZATION STEP: FACTORIALS FOR THE PHASE SPACE WEIGHT - IF(IBEGIN.NE.0) GOTO 103 - IBEGIN=1 - TWOPI=8.*DATAN(1.D0) - PO2LOG=LOG(TWOPI/4.) - Z(2)=PO2LOG - DO 101 K=3,(NEXTERNAL-NINCOMING) - 101 Z(K)=Z(K-1)+PO2LOG-2.*LOG(DFLOAT(K-2)) - DO 102 K=3,(NEXTERNAL-NINCOMING) - 102 Z(K)=(Z(K)-LOG(DFLOAT(K-1))) -C -C CHECK ON THE NUMBER OF PARTICLES - 103 IF(N.GT.1.AND.N.LT.101) GOTO 104 - PRINT 1001,N - STOP -C -C CHECK WHETHER TOTAL ENERGY IS SUFFICIENT; COUNT NONZERO MASSES - 104 XMT=0. - NM=0 - DO 105 I=1,N - IF(XM(I).NE.0.D0) NM=NM+1 - 105 XMT=XMT+ABS(XM(I)) - IF(XMT.LE.ET) GOTO 201 - PRINT 1002,XMT,ET - STOP -C -C THE PARAMETER VALUES ARE NOW ACCEPTED -C -C GENERATE N MASSLESS MOMENTA IN INFINITE PHASE SPACE - 201 DO 202 I=1,N - R1=RN(1) - C=2.*R1-1. - S=SQRT(1.-C*C) - F=TWOPI*RN(2) - R1=RN(3) - R2=RN(4) - Q(4,I)=-LOG(R1*R2) - Q(3,I)=Q(4,I)*C - Q(2,I)=Q(4,I)*S*COS(F) - 202 Q(1,I)=Q(4,I)*S*SIN(F) -C -C CALCULATE THE PARAMETERS OF THE CONFORMAL TRANSFORMATION - DO 203 I=1,4 - 203 R(I)=0. - DO 204 I=1,N - DO 204 K=1,4 - 204 R(K)=R(K)+Q(K,I) - RMAS=SQRT(R(4)**2-R(3)**2-R(2)**2-R(1)**2) - DO 205 K=1,3 - 205 B(K)=-R(K)/RMAS - G=R(4)/RMAS - A=1./(1.+G) - X=ET/RMAS -C -C TRANSFORM THE Q'S CONFORMALLY INTO THE P'S - DO 207 I=1,N - BQ=B(1)*Q(1,I)+B(2)*Q(2,I)+B(3)*Q(3,I) - DO 206 K=1,3 - 206 P(K,I)=X*(Q(K,I)+B(K)*(Q(4,I)+A*BQ)) - 207 P(4,I)=X*(G*Q(4,I)+BQ) -C -C CALCULATE WEIGHT AND POSSIBLE WARNINGS - WT=PO2LOG - IF(N.NE.2) WT=(2.*N-4.)*LOG(ET)+Z(N) - IF(WT.GE.-180.D0) GOTO 208 - IF(IWARN(1).LE.5) PRINT 1004,WT - IWARN(1)=IWARN(1)+1 - 208 IF(WT.LE. 174.D0) GOTO 209 - IF(IWARN(2).LE.5) PRINT 1005,WT - IWARN(2)=IWARN(2)+1 -C -C RETURN FOR WEIGHTED MASSLESS MOMENTA - 209 IF(NM.NE.0) GOTO 210 -C RETURN LOG OF WEIGHT - WT=WT - RETURN -C -C MASSIVE PARTICLES: RESCALE THE MOMENTA BY A FACTOR X - 210 XMAX=SQRT(1.-(XMT/ET)**2) - DO 301 I=1,N - XM2(I)=XM(I)**2 - 301 P2(I)=P(4,I)**2 - ITER=0 - X=XMAX - ACCU=ET*ACC - 302 F0=-ET - G0=0. - X2=X*X - DO 303 I=1,N - E(I)=SQRT(XM2(I)+X2*P2(I)) - F0=F0+E(I) - 303 G0=G0+P2(I)/E(I) - IF(ABS(F0).LE.ACCU) GOTO 305 - ITER=ITER+1 - IF(ITER.LE.ITMAX) GOTO 304 - PRINT 1006,ITMAX - GOTO 305 - 304 X=X-F0/(X*G0) - GOTO 302 - 305 DO 307 I=1,N - V(I)=X*P(4,I) - DO 306 K=1,3 - 306 P(K,I)=X*P(K,I) - 307 P(4,I)=E(I) -C -C CALCULATE THE MASS-EFFECT WEIGHT FACTOR - WT2=1. - WT3=0. - DO 308 I=1,N - WT2=WT2*V(I)/E(I) - 308 WT3=WT3+V(I)**2/E(I) - WTM=(2.*N-3.)*LOG(X)+LOG(WT2/WT3*ET) -C -C RETURN FOR WEIGHTED MASSIVE MOMENTA - WT=WT+WTM - IF(WT.GE.-180.D0) GOTO 309 - IF(IWARN(3).LE.5) PRINT 1004,WT - IWARN(3)=IWARN(3)+1 - 309 IF(WT.LE. 174.D0) GOTO 310 - IF(IWARN(4).LE.5) PRINT 1005,WT - IWARN(4)=IWARN(4)+1 -C RETURN LOG OF WEIGHT - 310 WT=WT - RETURN -C - 1001 FORMAT(' RAMBO FAILS: # OF PARTICLES =',I5,' IS NOT ALLOWED') - 1002 FORMAT(' RAMBO FAILS: TOTAL MASS =',D15.6,' IS NOT',' SMALLER' - $ //' THAN TOTAL ENERGY =',D15.6) - 1004 FORMAT(' RAMBO WARNS: WEIGHT = EXP(',F20.9,') MAY UNDERFLOW') - 1005 FORMAT(' RAMBO WARNS: WEIGHT = EXP(',F20.9,') MAY OVERFLOW') - 1006 FORMAT(' RAMBO WARNS:',I3,' ITERATIONS DID NOT GIVE THE', - $ ' DESIRED ACCURACY =',D15.6) - END - - FUNCTION RN(IDUMMY) - REAL*8 RN,RAN - SAVE INIT - DATA INIT /1/ - IF (INIT.EQ.1) THEN - INIT=0 - CALL RMARIN(1802,9373) - END IF -C - 10 CALL RANMAR(RAN) - IF (RAN.LT.1D-16) GOTO 10 - RN=RAN -C - END - - - - SUBROUTINE RANMAR(RVEC) -C ----------------- -C Universal random number generator proposed by Marsaglia and Zaman -C in report FSU-SCRI-87-50 -C In this version RVEC is a double precision variable. - IMPLICIT REAL*8(A-H,O-Z) - COMMON/ RASET1 / RANU(97),RANC,RANCD,RANCM - COMMON/ RASET2 / IRANMR,JRANMR - SAVE /RASET1/,/RASET2/ - UNI = RANU(IRANMR) - RANU(JRANMR) - IF(UNI .LT. 0D0) UNI = UNI + 1D0 - RANU(IRANMR) = UNI - IRANMR = IRANMR - 1 - JRANMR = JRANMR - 1 - IF(IRANMR .EQ. 0) IRANMR = 97 - IF(JRANMR .EQ. 0) JRANMR = 97 - RANC = RANC - RANCD - IF(RANC .LT. 0D0) RANC = RANC + RANCM - UNI = UNI - RANC - IF(UNI .LT. 0D0) UNI = UNI + 1D0 - RVEC = UNI - END - - SUBROUTINE RMARIN(IJ,KL) -C ----------------- -C Initializing routine for RANMAR, must be called before generating -C any pseudorandom numbers with RANMAR. The input values should be -C in -C the ranges 0<=ij<=31328 ; 0<=kl<=30081 - IMPLICIT REAL*8(A-H,O-Z) - COMMON/ RASET1 / RANU(97),RANC,RANCD,RANCM - COMMON/ RASET2 / IRANMR,JRANMR - SAVE /RASET1/,/RASET2/ -C This shows correspondence between the simplified input seeds IJ, -C KL -C and the original Marsaglia-Zaman seeds I,J,K,L. -C To get the standard values in the Marsaglia-Zaman paper -C (i=12,j=34 -C k=56,l=78) put ij=1802, kl=9373 - I = MOD( IJ/177 , 177 ) + 2 - J = MOD( IJ , 177 ) + 2 - K = MOD( KL/169 , 178 ) + 1 - L = MOD( KL , 169 ) - DO 300 II = 1 , 97 - S = 0D0 - T = .5D0 - DO 200 JJ = 1 , 24 - M = MOD( MOD(I*J,179)*K , 179 ) - I = J - J = K - K = M - L = MOD( 53*L+1 , 169 ) - IF(MOD(L*M,64) .GE. 32) S = S + T - T = .5D0*T - 200 CONTINUE - RANU(II) = S - 300 CONTINUE - RANC = 362436D0 / 16777216D0 - RANCD = 7654321D0 / 16777216D0 - RANCM = 16777213D0 / 16777216D0 - IRANMR = 97 - JRANMR = 33 - END - - - - - - - diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/coupl.inc b/UNITTEST_proc/SubProcesses/P0_gg_ttx/coupl.inc deleted file mode 120000 index daef53f7ac..0000000000 --- a/UNITTEST_proc/SubProcesses/P0_gg_ttx/coupl.inc +++ /dev/null @@ -1 +0,0 @@ -../coupl.inc \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/cts_mpc.h b/UNITTEST_proc/SubProcesses/P0_gg_ttx/cts_mpc.h deleted file mode 120000 index cfea8d8631..0000000000 --- a/UNITTEST_proc/SubProcesses/P0_gg_ttx/cts_mpc.h +++ /dev/null @@ -1 +0,0 @@ -../cts_mpc.h \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/cts_mprec.h b/UNITTEST_proc/SubProcesses/P0_gg_ttx/cts_mprec.h deleted file mode 120000 index 1d74785701..0000000000 --- a/UNITTEST_proc/SubProcesses/P0_gg_ttx/cts_mprec.h +++ /dev/null @@ -1 +0,0 @@ -../cts_mprec.h \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/global_specs.inc b/UNITTEST_proc/SubProcesses/P0_gg_ttx/global_specs.inc deleted file mode 120000 index 5bfc3e70cd..0000000000 --- a/UNITTEST_proc/SubProcesses/P0_gg_ttx/global_specs.inc +++ /dev/null @@ -1 +0,0 @@ -../global_specs.inc \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/improve_ps.f b/UNITTEST_proc/SubProcesses/P0_gg_ttx/improve_ps.f deleted file mode 100644 index 9e4f86735e..0000000000 --- a/UNITTEST_proc/SubProcesses/P0_gg_ttx/improve_ps.f +++ /dev/null @@ -1,1014 +0,0 @@ - SUBROUTINE ML5_0_IMPROVE_PS_POINT_PRECISION(P) - IMPLICIT NONE -C -C CONSTANTS -C - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) -C -C ARGUMENTS -C - DOUBLE PRECISION P(0:3,NEXTERNAL) - REAL*16 QP_P(0:3,NEXTERNAL) -C -C LOCAL VARIABLES -C - INTEGER I,J - -C ---------- -C BEGIN CODE -C ---------- - - DO I=1,NEXTERNAL - DO J=0,3 - QP_P(J,I)=P(J,I) - ENDDO - ENDDO - - CALL ML5_0_MP_IMPROVE_PS_POINT_PRECISION(QP_P) - - DO I=1,NEXTERNAL - DO J=0,3 - P(J,I)=QP_P(J,I) - ENDDO - ENDDO - - END - - - SUBROUTINE ML5_0_MP_IMPROVE_PS_POINT_PRECISION(P) - IMPLICIT NONE -C -C CONSTANTS -C - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) -C -C ARGUMENTS -C - REAL*16 P(0:3,NEXTERNAL) -C -C LOCAL VARIABLES -C - INTEGER I,J - INTEGER ERRCODE,ERRCODETMP - REAL*16 NEWP(0:3,NEXTERNAL) -C -C FUNCTIONS -C - LOGICAL ML5_0_MP_IS_PHYSICAL -C -C SAVED VARIABLES -C - INCLUDE 'MadLoopParams.inc' -C -C SAVED VARIABLES -C - INTEGER WARNED - DATA WARNED/0/ - - LOGICAL TOLD_SUPPRESS - DATA TOLD_SUPPRESS/.FALSE./ -C ---------- -C BEGIN CODE -C ---------- - -C ERROR CODES CONVENTION -C -C 1 :: None physical PS point input -C 100-1000 :: Error in the origianl method for restoring -C precision -C 1000-9999 :: Error when restoring precision ala PSMC -C - ERRCODETMP=0 - ERRCODE=0 - - DO J=1,NEXTERNAL - DO I=0,3 - NEWP(I,J)=P(I,J) - ENDDO - ENDDO - -C Check the sanity of the original PS point - IF (.NOT.ML5_0_MP_IS_PHYSICAL(NEWP,WARNED)) THEN - ERRCODE = 1 - WRITE(*,*) 'ERROR:: The input PS point is not precise enough.' - GOTO 100 - ENDIF - -C Now restore the precision - IF (IMPROVEPSPOINT.EQ.1) THEN - CALL ML5_0_MP_PSMC_IMPROVE_PS_POINT_PRECISION(NEWP,ERRCODE - $ ,WARNED) - ELSEIF((IMPROVEPSPOINT.EQ.2).OR.(IMPROVEPSPOINT.LE.0)) THEN - CALL ML5_0_MP_ORIG_IMPROVE_PS_POINT_PRECISION(NEWP,ERRCODE - $ ,WARNED) - ENDIF - IF (ERRCODE.NE.0) THEN - IF (WARNED.LT.20) THEN - WRITE(*,*) 'INFO:: Attempting to rescue the precision' - $ //' improvement with an alternative method.' - WARNED=WARNED+1 - ENDIF - IF (IMPROVEPSPOINT.EQ.1) THEN - CALL ML5_0_MP_ORIG_IMPROVE_PS_POINT_PRECISION(NEWP - $ ,ERRCODETMP,WARNED) - ELSEIF((IMPROVEPSPOINT.EQ.2).OR.(IMPROVEPSPOINT.LE.0)) THEN - CALL ML5_0_MP_PSMC_IMPROVE_PS_POINT_PRECISION(NEWP - $ ,ERRCODETMP,WARNED) - ENDIF - IF (ERRCODETMP.NE.0) GOTO 100 - ENDIF - -C Report to the user or update the PS point. - - GOTO 101 - 100 CONTINUE - IF (WARNED.LT.20) THEN - WRITE(*,*) 'WARNING:: This PS point could not be improved.' - $ //' Error code = ',ERRCODE,ERRCODETMP - CALL ML5_0_MP_WRITE_MOM(P) - WARNED = WARNED +1 - ENDIF - GOTO 102 - 101 CONTINUE - DO J=1,NEXTERNAL - DO I=0,3 - P(I,J)=NEWP(I,J) - ENDDO - ENDDO - 102 CONTINUE - - IF (WARNED.GE.20.AND..NOT.TOLD_SUPPRESS) THEN - WRITE(*,*) 'INFO:: Further warnings from the improve_ps' - $ //' routine will now be supressed.' - TOLD_SUPPRESS=.TRUE. - ENDIF - - END - - - FUNCTION ML5_0_MP_IS_CLOSE(P,NEWP,WARNED) - IMPLICIT NONE -C -C CONSTANTS -C - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - REAL*16 ZERO - PARAMETER (ZERO=0.0E+00_16) - REAL*16 THRS_CLOSE - PARAMETER (THRS_CLOSE=1.0E-02_16) -C -C ARGUMENTS -C - REAL*16 P(0:3,NEXTERNAL), NEWP(0:3,NEXTERNAL) - LOGICAL ML5_0_MP_IS_CLOSE - INTEGER WARNED -C -C LOCAL VARIABLES -C - INTEGER I,J - REAL*16 REF,REF2 - DOUBLE PRECISION BUFFDP - -C NOW MAKE SURE THE SHIFTED POINT IS NOT TOO FAR FROM THE ORIGINAL -C ONE - ML5_0_MP_IS_CLOSE = .TRUE. - REF = ZERO - REF2 = ZERO - DO J=1,NEXTERNAL - DO I=0,3 - REF2 = REF2 + ABS(P(I,J)) - REF = REF + ABS(P(I,J)-NEWP(I,J)) - ENDDO - ENDDO - - IF ((REF/REF2).GT.THRS_CLOSE) THEN - ML5_0_MP_IS_CLOSE = .FALSE. - IF (WARNED.LT.20) THEN - BUFFDP = (REF/REF2) - WRITE(*,*) 'WARNING:: The improved PS point is too far from' - $ //' the original one',BUFFDP - WARNED=WARNED+1 - ENDIF - ENDIF - - END - - FUNCTION ML5_0_MP_IS_PHYSICAL(P,WARNED) - IMPLICIT NONE -C -C CONSTANTS -C - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INTEGER NINITIAL - PARAMETER (NINITIAL=2) - REAL*16 ZERO - PARAMETER (ZERO=0.0E+00_16) - REAL*16 MP__ZERO - PARAMETER (MP__ZERO=ZERO) - REAL*16 ONE - PARAMETER (ONE=1.0E+00_16) - REAL*16 TWO - PARAMETER (TWO=2.0E+00_16) - REAL*16 THRES_ONSHELL - PARAMETER (THRES_ONSHELL=1.0E-02_16) - REAL*16 THRES_FOURMOM - PARAMETER (THRES_FOURMOM=1.0E-06_16) -C -C ARGUMENTS -C - REAL*16 P(0:3,NEXTERNAL) - LOGICAL ML5_0_MP_IS_PHYSICAL - INTEGER WARNED -C -C LOCAL VARIABLES -C - INTEGER I,J - REAL*16 BUFF,REF - REAL*16 MASSES(NEXTERNAL) - DOUBLE PRECISION BUFFDPA,BUFFDPB -C -C GLOBAL VARIABLES -C - - INCLUDE 'mp_coupl.inc' - - MASSES(1)=MP__ZERO - MASSES(2)=MP__ZERO - MASSES(3)=MP__MDL_MT - MASSES(4)=MP__MDL_MT - -C ---------- -C BEGIN CODE -C ---------- - - ML5_0_MP_IS_PHYSICAL = .TRUE. - -C WE FIRST CHECK THAT THE INPUT PS POINT IS REASONABLY PHYSICAL -C FOR THAT WE NEED A REFERENCE SCALE - REF=ZERO - DO J=1,NEXTERNAL - REF=REF+ABS(P(0,J)) - ENDDO - DO I=0,3 - BUFF=ZERO - DO J=1,NINITIAL - BUFF=BUFF-P(I,J) - ENDDO - DO J=NINITIAL+1,NEXTERNAL - BUFF=BUFF+P(I,J) - ENDDO - IF ((BUFF/REF).GT.THRES_FOURMOM) THEN - IF (WARNED.LT.20) THEN - BUFFDPA = (BUFF/REF) - WRITE(*,*) 'ERROR:: Four-momentum conservation is not' - $ //' accurate enough, ',BUFFDPA - CALL ML5_0_MP_WRITE_MOM(P) - WARNED=WARNED+1 - ENDIF - ML5_0_MP_IS_PHYSICAL = .FALSE. - ENDIF - ENDDO - REF = REF / (ONE*NEXTERNAL) - DO I=1,NEXTERNAL - REF=ABS(P(0,I))+ABS(P(1,I))+ABS(P(2,I))+ABS(P(3,I)) - IF ((SQRT(ABS(P(0,I)**2-P(1,I)**2-P(2,I)**2-P(3,I)**2-MASSES(I) - $ **2))/REF).GT.THRES_ONSHELL) THEN - IF (WARNED.LT.20) THEN - BUFFDPA=MASSES(I) - BUFFDPB=(SQRT(ABS(P(0,I)**2-P(1,I)**2-P(2,I)**2-P(3,I)**2 - $ -MASSES(I)**2))/REF) - WRITE(*,*) 'ERROR:: Onshellness of the momentum of' - $ //' particle ',I,' of mass ',BUFFDPA,' is not accurate' - $ //' enough, ',BUFFDPB - CALL ML5_0_MP_WRITE_MOM(P) - WARNED=WARNED+1 - ENDIF - ML5_0_MP_IS_PHYSICAL = .FALSE. - ENDIF - ENDDO - - END - - SUBROUTINE ML5_0_WRITE_MOM(P) - IMPLICIT NONE - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INTEGER NINITIAL - PARAMETER (NINITIAL=2) - DOUBLE PRECISION ZERO - PARAMETER (ZERO=0.0D0) - DOUBLE PRECISION ML5_0_MDOT - - INTEGER I,J - -C -C ARGUMENTS -C - DOUBLE PRECISION P(0:3,NEXTERNAL),PSUM(0:3) - DO I=0,3 - PSUM(I)=ZERO - DO J=1,NINITIAL - PSUM(I)=PSUM(I)+P(I,J) - ENDDO - DO J=NINITIAL+1,NEXTERNAL - PSUM(I)=PSUM(I)-P(I,J) - ENDDO - ENDDO - WRITE (*,*) ' Phase space point:' - WRITE (*,*) ' ---------------------' - WRITE (*,*) ' E | px | py | pz | m ' - DO I=1,NEXTERNAL - WRITE (*,'(1x,5e27.17)') P(0,I),P(1,I),P(2,I),P(3,I) - $ ,SQRT(ABS(ML5_0_MDOT(P(0,I),P(0,I)))) - ENDDO - WRITE (*,*) ' Four-momentum conservation sum:' - WRITE (*,'(1x,4e27.17)') PSUM(0),PSUM(1),PSUM(2),PSUM(3) - WRITE (*,*) ' ---------------------' - END - - DOUBLE PRECISION FUNCTION ML5_0_MDOT(P1,P2) - IMPLICIT NONE - DOUBLE PRECISION P1(0:3),P2(0:3) - ML5_0_MDOT=P1(0)*P2(0)-P1(1)*P2(1)-P1(2)*P2(2)-P1(3)*P2(3) - RETURN - END - - SUBROUTINE ML5_0_MP_WRITE_MOM(P) - IMPLICIT NONE - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INTEGER NINITIAL - PARAMETER (NINITIAL=2) - REAL*16 ZERO - PARAMETER (ZERO=0.0E+00_16) - REAL*16 ML5_0_MP_MDOT - - INTEGER I,J - -C -C ARGUMENTS -C - REAL*16 P(0:3,NEXTERNAL),PSUM(0:3),DOT - DOUBLE PRECISION DP_P(0:3,NEXTERNAL),DP_PSUM(0:3),DP_DOT - - DO I=0,3 - PSUM(I)=ZERO - DO J=1,NINITIAL - PSUM(I)=PSUM(I)+P(I,J) - ENDDO - DO J=NINITIAL+1,NEXTERNAL - PSUM(I)=PSUM(I)-P(I,J) - ENDDO - ENDDO - -C The GCC4.7 compiler on SLC machines has trouble to write out -C quadruple precision variable with the write(*,*) statement. I -C therefore perform the cast by hand - DO I=0,3 - DP_PSUM(I)=PSUM(I) - DO J=1,NEXTERNAL - DP_P(I,J)=P(I,J) - ENDDO - ENDDO - - WRITE (*,*) ' Phase space point:' - WRITE (*,*) ' ---------------------' - WRITE (*,*) ' E | px | py | pz | m ' - DO I=1,NEXTERNAL - DOT=SQRT(ABS(ML5_0_MP_MDOT(P(0,I),P(0,I)))) - DP_DOT=DOT - WRITE (*,'(1x,5e27.17)') DP_P(0,I),DP_P(1,I),DP_P(2,I),DP_P(3 - $ ,I),DP_DOT - ENDDO - WRITE (*,*) ' Four-momentum conservation sum:' - WRITE (*,'(1x,4e27.17)') DP_PSUM(0),DP_PSUM(1),DP_PSUM(2) - $ ,DP_PSUM(3) - WRITE (*,*) ' ---------------------' - END - - REAL*16 FUNCTION ML5_0_MP_MDOT(P1,P2) - IMPLICIT NONE - REAL*16 P1(0:3),P2(0:3) - ML5_0_MP_MDOT=P1(0)*P2(0)-P1(1)*P2(1)-P1(2)*P2(2)-P1(3)*P2(3) - RETURN - END - -C Rotate_PS rotates the PS point PS (without modifying it) -C stores the result in P and for the quadruple precision -C version , it also modifies the global variables -C PS and MP_DONE accordingly. - - SUBROUTINE ML5_0_ROTATE_PS(P_IN,P,ROTATION) - IMPLICIT NONE -C -C CONSTANTS -C - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) -C -C ARGUMENTS -C - DOUBLE PRECISION P_IN(0:3,NEXTERNAL),P(0:3,NEXTERNAL) - INTEGER ROTATION -C -C LOCAL VARIABLES -C - INTEGER I,J - -C ---------- -C BEGIN CODE -C ---------- - - DO I=1,NEXTERNAL -C rotation=1 => (xp=z,yp=-x,zp=-y) - IF(ROTATION.EQ.1) THEN - P(0,I)=P_IN(0,I) - P(1,I)=P_IN(3,I) - P(2,I)=-P_IN(1,I) - P(3,I)=-P_IN(2,I) -C rotation=2 => (xp=-z,yp=y,zp=x) - ELSEIF(ROTATION.EQ.2) THEN - P(0,I)=P_IN(0,I) - P(1,I)=-P_IN(3,I) - P(2,I)=P_IN(2,I) - P(3,I)=P_IN(1,I) - ELSE - P(0,I)=P_IN(0,I) - P(1,I)=P_IN(1,I) - P(2,I)=P_IN(2,I) - P(3,I)=P_IN(3,I) - ENDIF - ENDDO - - END - - - SUBROUTINE ML5_0_MP_ROTATE_PS(P_IN,P,ROTATION) - IMPLICIT NONE -C -C CONSTANTS -C - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) -C -C ARGUMENTS -C - REAL*16 P_IN(0:3,NEXTERNAL),P(0:3,NEXTERNAL) - INTEGER ROTATION -C -C LOCAL VARIABLES -C - INTEGER I,J -C -C GLOBAL VARIABLES -C - LOGICAL MP_DONE - COMMON/ML5_0_MP_DONE/MP_DONE - -C ---------- -C BEGIN CODE -C ---------- - - DO I=1,NEXTERNAL -C rotation=1 => (xp=z,yp=-x,zp=-y) - IF(ROTATION.EQ.1) THEN - P(0,I)=P_IN(0,I) - P(1,I)=P_IN(3,I) - P(2,I)=-P_IN(1,I) - P(3,I)=-P_IN(2,I) -C rotation=2 => (xp=-z,yp=y,zp=x) - ELSEIF(ROTATION.EQ.2) THEN - P(0,I)=P_IN(0,I) - P(1,I)=-P_IN(3,I) - P(2,I)=P_IN(2,I) - P(3,I)=P_IN(1,I) - ELSE - P(0,I)=P_IN(0,I) - P(1,I)=P_IN(1,I) - P(2,I)=P_IN(2,I) - P(3,I)=P_IN(3,I) - ENDIF - ENDDO - - MP_DONE = .FALSE. - - END - -C ***************************************************************** -C Beginning of the routine for restoring precision with V.H. method -C ***************************************************************** - - SUBROUTINE ML5_0_MP_ORIG_IMPROVE_PS_POINT_PRECISION(P,ERRCODE - $ ,WARNED) - IMPLICIT NONE -C -C CONSTANTS -C - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INTEGER NINITIAL - PARAMETER (NINITIAL=2) - REAL*16 ZERO - PARAMETER (ZERO=0.0E+00_16) - REAL*16 MP__ZERO - PARAMETER (MP__ZERO=ZERO) - REAL*16 ONE - PARAMETER (ONE=1.0E+00_16) - REAL*16 TWO - PARAMETER (TWO=2.0E+00_16) - REAL*16 THRS_TEST - PARAMETER (THRS_TEST=1.0E-15_16) -C -C ARGUMENTS -C - REAL*16 P(0:3,NEXTERNAL) - INTEGER ERRCODE, WARNED -C -C FUNCTIONS -C - LOGICAL ML5_0_MP_IS_CLOSE -C -C LOCAL VARIABLES -C - INTEGER I,J, P1, P2 -C PT STANDS FOR PTOT - REAL*16 PT(0:3), NEWP(0:3,NEXTERNAL) - REAL*16 BUFF,REF,REF2,DISCR - REAL*16 MASSES(NEXTERNAL) - REAL*16 SHIFTE(2),SHIFTZ(2) -C -C GLOBAL VARIABLES -C - - INCLUDE 'mp_coupl.inc' - - MASSES(1)=MP__ZERO - MASSES(2)=MP__ZERO - MASSES(3)=MP__MDL_MT - MASSES(4)=MP__MDL_MT - -C ---------- -C BEGIN CODE -C ---------- - ERRCODE = 0 - -C NOW WE MAKE SURE THAT THE PS POINT CAN BE IMPROVED BY THE -C ALGORITHM - REF=ZERO - DO J=1,NEXTERNAL - REF=REF+ABS(P(0,J)) - ENDDO - - IF (NINITIAL.NE.2) ERRCODE = 100 - - IF (ABS(P(1,1)/REF).GT.THRS_TEST.OR.ABS(P(2,1)/REF) - $ .GT.THRS_TEST.OR.ABS(P(1,2)/REF).GT.THRS_TEST.OR.ABS(P(2,2)/REF) - $ .GT.THRS_TEST) ERRCODE = 200 - - IF (MASSES(1).NE.ZERO.OR.MASSES(2).NE.ZERO) ERRCODE = 300 - - DO I=1,NEXTERNAL - IF (P(0,I).LT.ZERO) ERRCODE = 400 + I - ENDDO - - IF (ERRCODE.NE.0) GOTO 100 - -C WE FIRST SHIFT ALL THE FINAL STATE PARTICLES TO MAKE THEM -C EXACTLY ONSHELL - - DO I=0,3 - PT(I)=ZERO - ENDDO - DO I=NINITIAL+1,NEXTERNAL - DO J=0,3 - IF (J.EQ.3) THEN - NEWP(3,I)=SIGN(SQRT(ABS(P(0,I)**2-P(1,I)**2-P(2,I)**2 - $ -MASSES(I)**2)),P(3,I)) - ELSE - NEWP(J,I)=P(J,I) - ENDIF - PT(J)=PT(J)+NEWP(J,I) - ENDDO - ENDDO - -C WE CHOOSE P1 IN THE ALGORITHM TO ALWAYS BE THE PARTICLE WITH -C POSITIVE PZ - IF (P(3,1).GT.ZERO) THEN - P1=1 - P2=2 - ELSEIF (P(3,2).GT.ZERO) THEN - P1=2 - P2=1 - ELSE - ERRCODE = 500 - GOTO 100 - ENDIF - -C Now we calculate the shift to bring to P1 and P2 -C Mathematica gives -C ptotC = {ptotE, ptotX, ptotY, ptotZ}; -C pm1C = {pm1E + sm1E, pm1X, pm1Y, pm1Z + sm1Z}; -C {pm0E + sm0E, ptotX - pm1X, ptotY - pm1Y, pm0Z + sm0Z}; -C sol = Solve[{ptotC[[1]] - pm1C[[1]] - pm0C[[1]] == 0, -C ptotC[[4]] - pm1C[[4]] - pm0C[[4]] == 0, -C pm1C[[1]]^2 - pm1C[[2]]^2 - pm1C[[3]]^2 - pm1C[[4]]^2 == m1M^2, -C pm0C[[1]]^2 - pm0C[[2]]^2 - pm0C[[3]]^2 - pm0C[[4]]^2 == m2M^2}, -C {sm1E, sm1Z, sm0E, sm0Z}] // FullSimplify; -C (solC[[1]] /. {m1M -> 0, m2M -> 0} /. {pm1X -> 0, pm1Y -> 0}) -C END -C - DISCR = -PT(0)**2 + PT(1)**2 + PT(2)**2 + PT(3)**2 - IF (DISCR.LT.ZERO) DISCR = -DISCR - - SHIFTE(1) = (PT(0)*(-TWO*P(0,P1)*PT(0) + PT(0)**2 + PT(1)**2 + - $ PT(2)**2) + (TWO*P(0,P1) - PT(0))*PT(3)**2 + PT(3)*DISCR)/(TWO - $ *(PT(0) - PT(3))*(PT(0) + PT(3))) - SHIFTE(2) = -(PT(0)*(TWO*P(0,P2)*PT(0) - PT(0)**2 + PT(1)**2 + - $ PT(2)**2) + (-TWO*P(0,P2) + PT(0))*PT(3)**2 + PT(3)*DISCR) - $ /(TWO*(PT(0) - PT(3))*(PT(0) + PT(3))) - SHIFTZ(1) = (-TWO*P(3,P1)*(PT(0)**2 - PT(3)**2) + PT(3)*(PT(0)* - $ *2 + PT(1)**2 + PT(2)**2 - PT(3)**2) + PT(0)*DISCR)/(TWO*(PT(0) - $ **2 - PT(3)**2)) - SHIFTZ(2) = -(TWO*P(3,P2)*(PT(0)**2 - PT(3)**2) + PT(3)*(-PT(0)* - $ *2 + PT(1)**2 + PT(2)**2 + PT(3)**2) + PT(0)*DISCR)/(TWO*(PT(0) - $ **2 - PT(3)**2)) - NEWP(0,P1) = P(0,P1)+SHIFTE(1) - NEWP(3,P1) = P(3,P1)+SHIFTZ(1) - NEWP(0,P2) = P(0,P2)+SHIFTE(2) - NEWP(3,P2) = P(3,P2)+SHIFTZ(2) - NEWP(1,P2) = P(1,P2) - NEWP(2,P2) = P(2,P2) - DO J=1,2 - REF=ZERO - DO I=NINITIAL+1,NEXTERNAL - REF = REF + P(J,I) - ENDDO - REF = REF - P(J,P2) - NEWP(J,P1) = REF - ENDDO - - IF (.NOT.ML5_0_MP_IS_CLOSE(P,NEWP,WARNED)) THEN - ERRCODE=999 - GOTO 100 - ENDIF - - DO J=1,NEXTERNAL - DO I=0,3 - P(I,J)=NEWP(I,J) - ENDDO - ENDDO - - 100 CONTINUE - - END - -C ***************************************************************** -C Beginning of the routine for restoring precision a la PSMC -C ***************************************************************** - - SUBROUTINE ML5_0_MP_PSMC_IMPROVE_PS_POINT_PRECISION(P,ERRCODE - $ ,WARNED) - IMPLICIT NONE -C -C CONSTANTS -C - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INTEGER NINITIAL - PARAMETER (NINITIAL=2) - REAL*16 ZERO - PARAMETER (ZERO=0.0E+00_16) - REAL*16 MP__ZERO - PARAMETER (MP__ZERO=ZERO) - REAL*16 ONE - PARAMETER (ONE=1.0E+00_16) - REAL*16 TWO - PARAMETER (TWO=2.0E+00_16) - REAL*16 CONSISTENCY_THRES - PARAMETER (CONSISTENCY_THRES=1.0E-25_16) - - INTEGER NAPPROXZEROS - PARAMETER (NAPPROXZEROS=3) - -C -C ARGUMENTS -C - REAL*16 P(0:3,NEXTERNAL) - INTEGER ERRCODE,ERROR,WARNED -C -C FUNCTIONS -C - LOGICAL ML5_0_MP_IS_CLOSE -C -C LOCAL VARIABLES -C - INTEGER I,J, P1, P2 - REAL*16 NEWP(0:3,NEXTERNAL), PBUFF(0:3) - REAL*16 BUFF, BUFF2, XSCALE, APPROX_ZEROS(NAPPROXZEROS) - REAL*16 MASSES(NEXTERNAL) -C -C GLOBAL VARIABLES -C - - INCLUDE 'mp_coupl.inc' - -C ---------- -C BEGIN CODE -C ---------- - - MASSES(1)=MP__ZERO - MASSES(2)=MP__ZERO - MASSES(3)=MP__MDL_MT - MASSES(4)=MP__MDL_MT - - ERRCODE = 0 - XSCALE = ONE - -C Define the seeds which should be tried - APPROX_ZEROS(1)=1.0E+00_16 - APPROX_ZEROS(2)=1.1E+00_16 - APPROX_ZEROS(3)=0.9E+00_16 - -C Start by copying the momenta - DO I=1,NEXTERNAL - DO J=0,3 - NEWP(J,I)=P(J,I) - ENDDO - ENDDO - -C First make sur that the space like momentum is exactly conserved - DO J=0,3 - PBUFF(J)=ZERO - ENDDO - DO I=1,NINITIAL - DO J=1,3 - PBUFF(J)=PBUFF(J)+NEWP(J,I) - ENDDO - ENDDO - DO I=NINITIAL+1,NEXTERNAL-1 - DO J=1,3 - PBUFF(J)=PBUFF(J)-NEWP(J,I) - ENDDO - ENDDO - DO J=1,3 - NEWP(J,NEXTERNAL)=PBUFF(J) - ENDDO - -C Now find the 'x' rescaling factor - DO I=1,NAPPROXZEROS - CALL ML5_0_FINDX(NEWP,APPROX_ZEROS(I),XSCALE,ERROR) - IF(ERROR.EQ.0) THEN - GOTO 1001 - ELSE - ERRCODE=ERRCODE+(10**(I-1))*ERROR - ENDIF - ENDDO - IF (WARNED.LT.20) THEN - WRITE(*,*) 'WARNING:: Could not find the proper rescaling' - $ //' factor x. Restoring precision ala PSMC will therefore not' - $ //' be used.' - WARNED=WARNED+1 - ENDIF - IF (ERRCODE.LT.1000) THEN - ERRCODE=ERRCODE+1000 - ENDIF - GOTO 1000 - 1001 CONTINUE - ERRCODE = 0 - -C Apply the rescaling - DO I=1,NEXTERNAL - DO J=1,3 -C Consider scaling by x**2 for the first particle so that -C the algorithm for numerically solving for XSCALE has a -C non-vanishing -C derivative in the case that all particle are massless. - IF (I.EQ.1) THEN - NEWP(J,I)=NEWP(J,I)*XSCALE**2 - ELSE - NEWP(J,I)=NEWP(J,I)*XSCALE - ENDIF - ENDDO - ENDDO - -C Now restore exact onshellness of the particles. - DO I=1,NEXTERNAL - BUFF=MASSES(I)**2 - DO J=1,3 - BUFF=BUFF+NEWP(J,I)**2 - ENDDO - NEWP(0,I)=SQRT(BUFF) - ENDDO - -C Consistency check - BUFF=ZERO - BUFF2=ZERO - DO I=1,NINITIAL - BUFF=BUFF-NEWP(0,I) - BUFF2=BUFF2+NEWP(0,I) - ENDDO - DO I=NINITIAL+1,NEXTERNAL - BUFF=BUFF+NEWP(0,I) - BUFF2=BUFF2+NEWP(0,I) - ENDDO - IF ((ABS(BUFF)/BUFF2).GT.CONSISTENCY_THRES) THEN - IF (WARNED.LT.20) THEN - WRITE(*,*) 'WARNING:: The consistency check in the a la PSMC' - $ //' precision restoring algorithm failed. The result will' - $ //' therefore not be used.' - WARNED=WARNED+1 - ENDIF - ERRCODE = 1000 - GOTO 1000 - ENDIF - - IF (.NOT.ML5_0_MP_IS_CLOSE(P,NEWP,WARNED)) THEN - ERRCODE=999 - GOTO 1000 - ENDIF - - DO J=1,NEXTERNAL - DO I=0,3 - P(I,J)=NEWP(I,J) - ENDDO - ENDDO - - 1000 CONTINUE - - END - - - SUBROUTINE ML5_0_FINDX(P,SEED,XSCALE,ERROR) - IMPLICIT NONE -C -C CONSTANTS -C - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INTEGER NINITIAL - PARAMETER (NINITIAL=2) - REAL*16 ZERO - PARAMETER (ZERO=0.0E+00_16) - REAL*16 MP__ZERO - PARAMETER (MP__ZERO=ZERO) - REAL*16 ONE - PARAMETER (ONE=1.0E+00_16) - REAL*16 TWO - PARAMETER (TWO=2.0E+00_16) - INTEGER MAXITERATIONS - PARAMETER (MAXITERATIONS=8) - REAL*16 CONVERGED - PARAMETER (CONVERGED=1.0E-26_16) -C -C ARGUMENTS -C - REAL*16 P(0:3,NEXTERNAL),SEED,XSCALE - INTEGER ERROR -C -C LOCAL VARIABLES -C - INTEGER I,J,ERR - REAL*16 PVECSQ(NEXTERNAL) - REAL*16 XN, XNP1,FVAL,DVAL - -C ---------- -C BEGIN CODE -C ---------- - - ERROR = 0 - XSCALE = SEED - XN = SEED - XNP1 = SEED - - DO I=1,NEXTERNAL - PVECSQ(I)=P(1,I)**2+P(2,I)**2+P(3,I)**2 - ENDDO - - DO I=1,MAXITERATIONS - CALL ML5_0_FUNCT(PVECSQ(1),XN,.FALSE.,ERR, FVAL) - IF (ERR.NE.0) THEN - ERROR=ERR - GOTO 710 - ENDIF - CALL ML5_0_FUNCT(PVECSQ(1),XN,.TRUE.,ERR, DVAL) - IF (ERR.NE.0) THEN - ERROR=ERR - GOTO 710 - ENDIF - XNP1=XN-(FVAL/DVAL) - IF((ABS(((XNP1-XN)*TWO)/(XNP1+XN))).LT.CONVERGED) THEN - XN=XNP1 - GOTO 700 - ENDIF - XN=XNP1 - ENDDO - ERROR=9 - GOTO 710 - - 700 CONTINUE -C For good measure, we iterate one last time - CALL ML5_0_FUNCT(PVECSQ(1),XN,.FALSE.,ERR, FVAL) - IF (ERR.NE.0) THEN - ERROR=ERR - GOTO 710 - ENDIF - CALL ML5_0_FUNCT(PVECSQ(1),XN,.TRUE.,ERR, DVAL) - IF (ERR.NE.0) THEN - ERROR=ERR - GOTO 710 - ENDIF - - XSCALE=XN-(FVAL/DVAL) - - 710 CONTINUE - - END - - SUBROUTINE ML5_0_FUNCT(PVECSQ,X,DERIVATIVE,ERROR,RES) - IMPLICIT NONE -C -C CONSTANTS -C - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INTEGER NINITIAL - PARAMETER (NINITIAL=2) - REAL*16 ZERO - PARAMETER (ZERO=0.0E+00_16) - REAL*16 MP__ZERO - PARAMETER (MP__ZERO=ZERO) - REAL*16 ONE - PARAMETER (ONE=1.0E+00_16) - REAL*16 TWO - PARAMETER (TWO=2.0E+00_16) -C -C ARGUMENTS -C - REAL*16 PVECSQ(NEXTERNAL),X,RES - INTEGER ERROR - LOGICAL DERIVATIVE -C -C LOCAL VARIABLES -C - INTEGER I,J - REAL*16 BUFF,FACTOR - REAL*16 MASSES(NEXTERNAL) -C -C GLOBAL VARIABLES -C - - INCLUDE 'mp_coupl.inc' - -C ---------- -C BEGIN CODE -C ---------- - - MASSES(1)=MP__ZERO - MASSES(2)=MP__ZERO - MASSES(3)=MP__MDL_MT - MASSES(4)=MP__MDL_MT - - ERROR=0 - RES=ZERO - BUFF=ZERO - -C Consider scaling by x**2 for the first particle so that -C the algorithm for numerically solving for XSCALE has a -C non-vanishing -C derivative in the case that all particle are massless. - - DO I=1,NEXTERNAL - IF (I.LE.NINITIAL) THEN - FACTOR=-ONE - ELSE - FACTOR=ONE - ENDIF - IF (I.EQ.1) THEN - BUFF=MASSES(I)**2+PVECSQ(I)*X**4 - ELSE - BUFF=MASSES(I)**2+PVECSQ(I)*X**2 - ENDIF - IF (BUFF.LT.ZERO) THEN - RES=ZERO - ERROR = 1 - GOTO 800 - ENDIF - IF (DERIVATIVE) THEN - IF (I.EQ.1) THEN - RES=RES + FACTOR*((2*X*PVECSQ(I))/SQRT(BUFF)) - ELSE - RES=RES + FACTOR*((X*PVECSQ(I))/SQRT(BUFF)) - ENDIF - ELSE - RES=RES + FACTOR*SQRT(BUFF) - ENDIF - ENDDO - - 800 CONTINUE - - END - diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/loop_matrix.f b/UNITTEST_proc/SubProcesses/P0_gg_ttx/loop_matrix.f deleted file mode 100644 index a99f72d8cd..0000000000 --- a/UNITTEST_proc/SubProcesses/P0_gg_ttx/loop_matrix.f +++ /dev/null @@ -1,1860 +0,0 @@ - SUBROUTINE ML5_0_SLOOPMATRIXHEL(P,HEL,ANS) - USE ALOHA_OBJECT - IMPLICIT NONE -C -C CONSTANTS -C - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - - INCLUDE 'nsquaredSO.inc' - -C -C ARGUMENTS -C - REAL*8 P(0:3,NEXTERNAL) - REAL*8 ANS(0:3,0:NSQUAREDSO) - INTEGER HEL, USERHEL - COMMON/ML5_0_USERCHOICE/USERHEL -C ---------- -C BEGIN CODE -C ---------- - USERHEL=HEL - CALL ML5_0_SLOOPMATRIX(P,ANS) - END - - LOGICAL FUNCTION ML5_0_IS_HEL_SELECTED(HELID) - IMPLICIT NONE -C -C CONSTANTS -C - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INTEGER NCOMB - PARAMETER (NCOMB=16) -C -C ARGUMENTS -C - INTEGER HELID -C -C LOCALS -C - INTEGER I,J - LOGICAL FOUNDIT -C -C GLOBALS -C - INTEGER HELC(NEXTERNAL,NCOMB) - COMMON/ML5_0_HELCONFIGS/HELC - - INTEGER POLARIZATIONS(0:NEXTERNAL,0:5) - COMMON/ML5_0_BEAM_POL/POLARIZATIONS -C ---------- -C BEGIN CODE -C ---------- - - ML5_0_IS_HEL_SELECTED = .TRUE. - IF (POLARIZATIONS(0,0).EQ.-1) THEN - RETURN - ENDIF - - DO I=1,NEXTERNAL - IF (POLARIZATIONS(I,0).EQ.-1) THEN - CYCLE - ENDIF - FOUNDIT = .FALSE. - DO J=1,POLARIZATIONS(I,0) - IF (HELC(I,HELID).EQ.POLARIZATIONS(I,J)) THEN - FOUNDIT = .TRUE. - EXIT - ENDIF - ENDDO - IF(.NOT.FOUNDIT) THEN - ML5_0_IS_HEL_SELECTED = .FALSE. - RETURN - ENDIF - ENDDO - RETURN - - END - - LOGICAL FUNCTION ML5_0_ISZERO(TOTEST, REFERENCE_VALUE, AMPLN) - IMPLICIT NONE -C -C CONSTANTS -C - INTEGER NLOOPAMPS - PARAMETER (NLOOPAMPS=129) -C -C ARGUMENTS -C - REAL*8 TOTEST, REFERENCE_VALUE - INTEGER AMPLN -C -C GLOBAL -C - INCLUDE 'MadLoopParams.inc' - - COMPLEX*16 AMPL(3,NLOOPAMPS) - LOGICAL S(NLOOPAMPS) - COMMON/ML5_0_AMPL/AMPL,S -C ---------- -C BEGIN CODE -C ---------- - IF(ABS(REFERENCE_VALUE).EQ.0.0D0) THEN - ML5_0_ISZERO=.FALSE. - WRITE(*,*) '##E02 ERRROR Reference value for comparison is' - $ //' zero.' - STOP - ELSE - ML5_0_ISZERO=((ABS(TOTEST)/ABS(REFERENCE_VALUE)).LT.ZEROTHRES) - ENDIF - IF(AMPLN.NE.-1) THEN - IF((.NOT.ML5_0_ISZERO).AND.(.NOT.S(AMPLN))) THEN - WRITE(*,*) '##W01 WARNING Contribution ',AMPLN,' is detected' - $ //' as contributing with CR=',(ABS(TOTEST) - $ /ABS(REFERENCE_VALUE)),' but is unstable.' - ENDIF - ENDIF - - END - - SUBROUTINE ML5_0_SLOOPMATRIX(P_USER,ANSRETURNED) - USE ALOHA_OBJECT -C -C Generated by MadGraph5_aMC@NLO v. 3.7.2, 2026-04-29 -C By the MadGraph5_aMC@NLO Development Team -C Visit launchpad.net/madgraph5 and amcatnlo.web.cern.ch -C -C Returns amplitude squared summed/avg over colors -C and helicities for the point in phase space P(0:3,NEXTERNAL) -C and external lines W(0:6,NEXTERNAL) -C -C Process: g g > t t~ QCD<=2 QED=0 [ virt = QCD ] -C - IMPLICIT NONE -C -C CONSTANTS -C - CHARACTER*512 PARAMFNAME,HELCONFIGFNAME,LOOPFILTERFNAME - CHARACTER*512 COLORNUMFNAME,COLORDENOMFNAME, HELFILTERFNAME - CHARACTER*512 PROC_PREFIX - PARAMETER ( PARAMFNAME='MadLoopParams.dat') - PARAMETER ( HELCONFIGFNAME='HelConfigs.dat') - PARAMETER ( LOOPFILTERFNAME='LoopFilter.dat') - PARAMETER ( HELFILTERFNAME='HelFilter.dat') - PARAMETER ( COLORNUMFNAME='ColorNumFactors.dat') - PARAMETER ( COLORDENOMFNAME='ColorDenomFactors.dat') - PARAMETER ( PROC_PREFIX='ML5_0_') - - INTEGER NBORNAMPS - PARAMETER (NBORNAMPS=3) - INTEGER NLOOPAMPS, NCTAMPS - PARAMETER (NLOOPAMPS=129, NCTAMPS=85) - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INTEGER NINITIAL - PARAMETER (NINITIAL=2) - INTEGER NWAVEFUNCS - PARAMETER (NWAVEFUNCS=10) - INTEGER NCOMB - PARAMETER (NCOMB=16) - REAL*8 ZERO - PARAMETER (ZERO=0D0) - REAL*16 MP__ZERO - PARAMETER (MP__ZERO=0E0_16) - COMPLEX*16 IMAG1 - PARAMETER (IMAG1=(0D0,1D0)) -C This parameter is designed for the check timing command of MG5 - LOGICAL SKIPLOOPEVAL - PARAMETER (SKIPLOOPEVAL=.FALSE.) - LOGICAL BOOTANDSTOP - PARAMETER (BOOTANDSTOP=.FALSE.) - INCLUDE 'nsquaredSO.inc' - INTEGER NSQUAREDSOP1 - PARAMETER (NSQUAREDSOP1=NSQUAREDSO+1) - INTEGER MAXSTABILITYLENGTH - DATA MAXSTABILITYLENGTH/20/ - COMMON/ML5_0_STABILITY_TESTS/MAXSTABILITYLENGTH -C -C ARGUMENTS -C - REAL*8 P_USER(0:3,NEXTERNAL) - REAL*8 ANSRETURNED(0:3,0:NSQUAREDSO) -C -C LOCAL VARIABLES -C - REAL*8 ANS(0:3) - INTEGER I,J,K,H - - CHARACTER*512 PARAMFN,HELCONFIGFN,LOOPFILTERFN,COLORNUMFN - $ ,COLORDENOMFN,HELFILTERFN - CHARACTER*512 TMP - SAVE PARAMFN - SAVE HELCONFIGFN - SAVE LOOPFILTERFN - SAVE COLORNUMFN - SAVE COLORDENOMFN - SAVE HELFILTERFN - - INTEGER HELPICKED_BU, CTMODEINIT_BU - REAL*8 MLSTABTHRES_BU -C P is the actual PS POINT used for the computation, and can be -C rotated for the stability test purposes. - REAL*8 P(0:3,NEXTERNAL) -C DP_RES STORES THE DOUBLE PRECISION RESULT OBTAINED FROM -C DIFFERENT EVALUATION METHODS IN ORDER TO ASSESS STABILITY. -C THE STAB_STAGE COUNTER I CORRESPONDANCE GOES AS FOLLOWS -C I=1 -> ORIGINAL PS, CTMODE=1 -C I=2 -> ORIGINAL PS, CTMODE=2, (ONLY WITH CTMODERUN=-1) -C I=3 -> PS WITH ROTATION 1, CTMODE=1, (ONLY WITH CTMODERUN=-2) -C I=4 -> PS WITH ROTATION 2, CTMODE=1, (ONLY WITH CTMODERUN=-3) -C I=5 -> POSSIBLY MORE EVALUATION METHODS IN THE FUTURE, MAX IS -C MAXSTABILITYLENGTH -C IF UNSTABLE IT GOES TO THE SAME PATTERN BUT STAB_INDEX IS THEN -C I+20. - LOGICAL EVAL_DONE(MAXSTABILITYLENGTH) - LOGICAL DOING_QP_EVALS - INTEGER STAB_INDEX,BASIC_CT_MODE - INTEGER N_DP_EVAL, N_QP_EVAL - DATA N_DP_EVAL/1/ - DATA N_QP_EVAL/1/ -C This is used for loop-induced where the reference scale for -C comparisons is infered from -C the previous points - REAL*8 NEXTREF - DATA NEXTREF/ZERO/ - INTEGER NPSPOINTS - DATA NPSPOINTS/0/ - LOGICAL FOUND_VALID_REDUCTION_METHOD - DATA FOUND_VALID_REDUCTION_METHOD/.FALSE./ - - REAL*8 ACC - REAL*8 DP_RES(3,MAXSTABILITYLENGTH) -C QP_RES STORES THE QUADRUPLE PRECISION RESULT OBTAINED FROM -C DIFFERENT EVALUATION METHODS IN ORDER TO ASSESS STABILITY. - REAL*8 QP_RES(3,MAXSTABILITYLENGTH) - INTEGER NHEL(NEXTERNAL), IC(NEXTERNAL) - INTEGER NATTEMPTS - DATA NATTEMPTS/0/ - DATA IC/NEXTERNAL*1/ - INTEGER FLAVOR(NEXTERNAL) - DATA FLAVOR /NEXTERNAL*1/ - REAL*8 BUFFR(3),TEMP(3),TEMP1,TEMP2 - COMPLEX*16 CFTOT - LOGICAL FOUNDHELFILTER,FOUNDLOOPFILTER - DATA FOUNDHELFILTER/.TRUE./ - DATA FOUNDLOOPFILTER/.TRUE./ - INTEGER IDEN - DATA IDEN/256/ - INTEGER HELAVGFACTOR - DATA HELAVGFACTOR/4/ -C For a 1>N process, them BEAMTWO_HELAVGFACTOR would be set to 1. - INTEGER BEAMS_HELAVGFACTOR(2) - DATA (BEAMS_HELAVGFACTOR(I),I=1,2)/2,2/ - LOGICAL DONEHELDOUBLECHECK - DATA DONEHELDOUBLECHECK/.FALSE./ - INTEGER NEPS - DATA NEPS/0/ -C Below are variables to bypass the checkphase and insure -C stability check to take place - LOGICAL OLD_CHECKPHASE, OLD_HELDOUBLECHECKED - LOGICAL OLD_GOODHEL(NCOMB) - LOGICAL OLD_GOODAMP(NLOOPAMPS,NCOMB) - - LOGICAL BYPASS_CHECK, ALWAYS_TEST_STABILITY - COMMON/ML5_0_BYPASS_CHECK/BYPASS_CHECK, ALWAYS_TEST_STABILITY -C -C FUNCTIONS -C - LOGICAL ML5_0_ISZERO - LOGICAL ML5_0_IS_HEL_SELECTED -C -C GLOBAL VARIABLES -C - INCLUDE 'process_info.inc' - INCLUDE 'coupl.inc' - INCLUDE 'mp_coupl.inc' - INCLUDE 'MadLoopParams.inc' - - INTEGER NTRY - DATA NTRY/0/ - LOGICAL CHECKPHASE - DATA CHECKPHASE/.TRUE./ - LOGICAL HELDOUBLECHECKED - DATA HELDOUBLECHECKED/.FALSE./ - REAL*8 REF - DATA REF/0.0D0/ - COMMON/ML5_0_INIT/NTRY,CHECKPHASE,HELDOUBLECHECKED,REF - -C THE LOGICAL BELOWS ARE JUST TO KEEP TRACK OF WHETHER THE MP_PS -C HAS BEEN SET YET OR NOT AND WHETER THE MP EXTERNAL WFS HAVE -C BEEN COMPUTED YET. - LOGICAL MP_DONE - DATA MP_DONE/.FALSE./ - COMMON/ML5_0_MP_DONE/MP_DONE - LOGICAL MP_PS_SET - DATA MP_PS_SET/.FALSE./ - COMMON/ML5_0_MP_PS_SET/MP_PS_SET - -C PS CAN POSSIBILY BE PASSED THROUGH IMPROVE_PS BUT IS NOT -C MODIFIED FOR THE PURPOSE OF THE STABILITY TEST -C EVEN THOUGH THEY ARE PUT IN COMMON BLOCK, FOR NOW THEY ARE NOT -C USED ANYWHERE ELSE - REAL*8 PS(0:3,NEXTERNAL) - COMMON/ML5_0_PSPOINT/PS -C AGAIN BELOW, MP_PS IS THE FIXED (POSSIBLY IMPROVED) MP PS POINT -C AND MP_P IS THE ONE WHICH CAN BE MODIFIED (I.E. ROTATED ETC.) -C FOR STABILITY PURPOSE -C EVEN THOUGH THEY ARE PUT IN COMMON BLOCK, FOR NOW THEY ARE NOT -C USED ANYWHERE ELSE THAN HERE AND SET_MP_PS() - REAL*16 MP_PS(0:3,NEXTERNAL),MP_P(0:3,NEXTERNAL) - COMMON/ML5_0_MP_PSPOINT/MP_PS,MP_P - - REAL*8 LSCALE - INTEGER CTMODE - COMMON/ML5_0_CT/LSCALE,CTMODE - - LOGICAL GOODHEL(NCOMB) - LOGICAL GOODAMP(NLOOPAMPS,NCOMB) - COMMON/ML5_0_FILTERS/GOODAMP,GOODHEL - - INTEGER HELPICKED - DATA HELPICKED/-1/ - COMMON/ML5_0_HELCHOICE/HELPICKED - INTEGER USERHEL - DATA USERHEL/-1/ - COMMON/ML5_0_USERCHOICE/USERHEL - - COMPLEX*16 AMP(NBORNAMPS,NCOMB) - COMMON/ML5_0_AMPS/AMP - TYPE(ALOHA) W(NWAVEFUNCS,NCOMB) - INTEGER VALIDH - COMMON/ML5_0_WFCTS/W - COMMON/ML5_0_VALIDH/VALIDH - - COMPLEX*16 AMPL(3,NLOOPAMPS) - LOGICAL S(NLOOPAMPS) - COMMON/ML5_0_AMPL/AMPL,S - - INTEGER CF_D(NLOOPAMPS,NBORNAMPS) - INTEGER CF_N(NLOOPAMPS,NBORNAMPS) - COMMON/ML5_0_CF/CF_D,CF_N - - INTEGER HELC(NEXTERNAL,NCOMB) - COMMON/ML5_0_HELCONFIGS/HELC - - REAL*8 PREC,USER_STAB_PREC - DATA USER_STAB_PREC/-1.0D0/ - COMMON/ML5_0_USER_STAB_PREC/USER_STAB_PREC - -C Return codes H,T,U correspond to the hundreds, tens and units -C building returncode, i.e. -C RETURNCODE=100*RET_CODE_H+10*RET_CODE_T+RET_CODE_U - - INTEGER RET_CODE_H,RET_CODE_T,RET_CODE_U - REAL*8 ACCURACY(0:NSQUAREDSO) - DATA (ACCURACY(I),I=0,NSQUAREDSO)/NSQUAREDSOP1*1.0D0/ - DATA RET_CODE_H,RET_CODE_T,RET_CODE_U/1,1,0/ - COMMON/ML5_0_ACC/ACCURACY,RET_CODE_H,RET_CODE_T,RET_CODE_U - -C Allows to forbid the zero helicity double check, no matter the -C value in MadLoopParams.dat -C This can be accessed with the SET_FORBID_HEL_DOUBLECHECK -C subroutine of MadLoopCommons.dat - LOGICAL FORBID_HEL_DOUBLECHECK - COMMON/FORBID_HEL_DOUBLECHECK/FORBID_HEL_DOUBLECHECK - - LOGICAL MP_DONE_ONCE - DATA MP_DONE_ONCE/.FALSE./ - COMMON/ML5_0_MP_DONE_ONCE/MP_DONE_ONCE - - CHARACTER(512) MLPATH - COMMON/MLPATH/MLPATH - - LOGICAL ML_INIT - COMMON/ML_INIT/ML_INIT - -C This variable controls the *local* initialization of this -C particular SubProcess. -C For example, the reading of the filters must be done -C independently by each SubProcess. - LOGICAL LOCAL_ML_INIT - DATA LOCAL_ML_INIT/.TRUE./ - -C Variables related to turning off the Lorentz rotation test when -C spin-2 particles are external - LOGICAL WARNED_LORENTZ_STAB_TEST_OFF - DATA WARNED_LORENTZ_STAB_TEST_OFF/.FALSE./ - INTEGER NROTATIONS_DP_BU,NROTATIONS_QP_BU - -C This array specify potential special requirements on the -C helicities to -C consider. POLARIZATIONS(0,0) is -1 if there is not such -C requirement. - INTEGER POLARIZATIONS(0:NEXTERNAL,0:5) - COMMON/ML5_0_BEAM_POL/POLARIZATIONS - -C ---------- -C BEGIN CODE -C ---------- - - IF(ML_INIT) THEN - CALL PRINT_MADLOOP_BANNER() - TMP = 'auto' - CALL SETMADLOOPPATH(TMP) - CALL JOINPATH(MLPATH,PARAMFNAME,PARAMFN) - CALL MADLOOPPARAMREADER(PARAMFN,.TRUE.) - IF (FORBID_HEL_DOUBLECHECK) THEN - DOUBLECHECKHELICITYFILTER = .FALSE. - ENDIF - ML_INIT = .FALSE. -C For now only CutTools is interfaced in the default mode. -C Samurai could follow. - DO I=1,SIZE(MLREDUCTIONLIB) - IF (MLREDUCTIONLIB(I).EQ.1) THEN - FOUND_VALID_REDUCTION_METHOD = .TRUE. - ENDIF - ENDDO - IF (.NOT.FOUND_VALID_REDUCTION_METHOD) THEN - WRITE(*,*) 'ERROR:: For now, only CutTools is interfaced to' - $ //' MadLoop in the non-optimized output.' - WRITE(*,*) 'ERROR:: Make sure to include 1 in the parameter' - $ //' MLReductionLib of the card MadLoopParams.dat' - STOP 1 - ENDIF - ENDIF - IF (LOCAL_ML_INIT) THEN -C Setup the file paths - CALL JOINPATH(MLPATH,PARAMFNAME,PARAMFN) - CALL JOINPATH(MLPATH,PROC_PREFIX,TMP) - CALL JOINPATH(TMP,HELCONFIGFNAME,HELCONFIGFN) - CALL JOINPATH(TMP,LOOPFILTERFNAME,LOOPFILTERFN) - CALL JOINPATH(TMP,COLORNUMFNAME,COLORNUMFN) - CALL JOINPATH(TMP,COLORDENOMFNAME,COLORDENOMFN) - CALL JOINPATH(TMP,HELFILTERFNAME,HELFILTERFN) - -C Make sure that the loop filter is disabled when there is -C spin-2 particles for 2>1 or 1>2 processes - IF(MAX_SPIN_EXTERNAL_PARTICLE.GT.3.AND.(NEXTERNAL.LE.3.AND.HELI - $CITYFILTERLEVEL.NE.0)) THEN - WRITE(*,*) '##INFO: Helicity filter deactivated for 2>1' - $ //' processes involving spin 2 particles.' - HELICITYFILTERLEVEL = 0 -C We write a dummy filter for structural reasons here - OPEN(1, FILE=HELFILTERFN, ERR=6116, STATUS='NEW' - $ ,ACTION='WRITE') - DO I=1,NCOMB - WRITE(1,*) 'T' - ENDDO - 6116 CONTINUE - CLOSE(1) - ENDIF - - OPEN(1, FILE=COLORNUMFN, ERR=104, STATUS='OLD', - $ ACTION='READ') - DO I=1,NLOOPAMPS - READ(1,*,END=105) (CF_N(I,J),J=1,NBORNAMPS) - ENDDO - GOTO 105 - 104 CONTINUE - STOP 'Color factors could not be initialized from file' - $ //' ML5_0_ColorNumFactors.dat. File not found' - 105 CONTINUE - CLOSE(1) - OPEN(1, FILE=COLORDENOMFN, ERR=106, STATUS='OLD', - $ ACTION='READ') - DO I=1,NLOOPAMPS - READ(1,*,END=107) (CF_D(I,J),J=1,NBORNAMPS) - ENDDO - GOTO 107 - 106 CONTINUE - STOP 'Color factors could not be initialized from file' - $ //' ML5_0_ColorDenomFactors.dat. File not found' - 107 CONTINUE - CLOSE(1) - OPEN(1, FILE=HELCONFIGFN, ERR=108, STATUS='OLD', - $ ACTION='READ') - DO H=1,NCOMB - READ(1,*,END=109) (HELC(I,H),I=1,NEXTERNAL) - ENDDO - GOTO 109 - 108 CONTINUE - STOP 'Color helictiy configurations could not be initialized' - $ //' from file ML5_0_HelConfigs.dat. File not found' - 109 CONTINUE - CLOSE(1) - IF(BOOTANDSTOP) THEN - WRITE(*,*) '##Stopped by user request.' - STOP - ENDIF - LOCAL_ML_INIT = .FALSE. - ENDIF - -C Make sure that lorentz rotation tests are not used if there is -C external loop wavefunction of spin 2 and that one specific -C helicity is asked - NROTATIONS_DP_BU = NROTATIONS_DP - NROTATIONS_QP_BU = NROTATIONS_QP - IF(MAX_SPIN_EXTERNAL_PARTICLE.GT.3.AND.USERHEL.NE.-1) THEN - IF(.NOT.WARNED_LORENTZ_STAB_TEST_OFF) THEN - WRITE(*,*) '##WARNING: Evaluation of a specific helicity was' - $ //' asked for this PS point, and there is a spin-2 (or' - $ //' higher) particle in the external states.' - WRITE(*,*) '##WARNING: As a result, MadLoop disabled the' - $ //' Lorentz rotation test for this phase-space point only.' - WRITE(*,*) '##WARNING: Further warning of that type' - $ //' suppressed.' - WARNED_LORENTZ_STAB_TEST_OFF = .FALSE. - ENDIF - NROTATIONS_QP=0 - NROTATIONS_DP=0 - ENDIF - - IF(NTRY.EQ.0) THEN - CALL ML5_0_SET_N_EVALS(N_DP_EVAL,N_QP_EVAL) - HELDOUBLECHECKED=(.NOT.DOUBLECHECKHELICITYFILTER) - $ .OR.(HELICITYFILTERLEVEL.EQ.0) - DO J=1,NCOMB - DO I=1,NCTAMPS - GOODAMP(I,J)=.TRUE. - ENDDO - ENDDO - OPEN(1, FILE=LOOPFILTERFN, ERR=100, STATUS='OLD', - $ ACTION='READ') - DO J=1,NCOMB - READ(1,*,END=101) (GOODAMP(I,J),I=NCTAMPS+1,NLOOPAMPS) - ENDDO - GOTO 101 - 100 CONTINUE - FOUNDLOOPFILTER=.FALSE. - DO J=1,NCOMB - DO I=NCTAMPS+1,NLOOPAMPS - GOODAMP(I,J)=(.NOT.USELOOPFILTER) - ENDDO - ENDDO - 101 CONTINUE - CLOSE(1) - IF (HELICITYFILTERLEVEL.EQ.0) THEN - FOUNDHELFILTER=.TRUE. - DO J=1,NCOMB - GOODHEL(J)=.TRUE. - ENDDO - GOTO 122 - ENDIF - OPEN(1, FILE=HELFILTERFN, ERR=102, STATUS='OLD', - $ ACTION='READ') - READ(1,*,END=103) (GOODHEL(I),I=1,NCOMB) - GOTO 103 - 102 CONTINUE - FOUNDHELFILTER=.FALSE. - DO J=1,NCOMB - GOODHEL(J)=.TRUE. - ENDDO - 103 CONTINUE - CLOSE(1) - 122 CONTINUE - ENDIF - - MP_DONE=.FALSE. - MP_DONE_ONCE=.FALSE. - MP_PS_SET=.FALSE. - STAB_INDEX=0 - DOING_QP_EVALS=.FALSE. - EVAL_DONE(1)=.TRUE. - DO I=2,MAXSTABILITYLENGTH - EVAL_DONE(I)=.FALSE. - ENDDO - -C Compute the born, for a specific helicity if asked so. - CALL ML5_0_SMATRIXHEL(P_USER,USERHEL,FLAVOR,ANS(0)) - - - IF (USER_STAB_PREC.GT.0.0D0) THEN - MLSTABTHRES_BU=MLSTABTHRES - MLSTABTHRES=USER_STAB_PREC -C In the initialization, I cannot perform stability test and -C therefore guarantee any precision - CTMODEINIT_BU=CTMODEINIT -C So either one choses quad precision directly -C CTMODEINIT=4 -C Or, because this is very slow, we keep the orignal value. The -C accuracy returned is -1 and tells the MC that he should not -C trust the evaluation for checks. - CTMODEINIT=CTMODEINIT_BU - ENDIF - - IF(.NOT.BYPASS_CHECK) THEN - NTRY=NTRY+1 - ENDIF - - IF(DONEHELDOUBLECHECK.AND.(.NOT.HELDOUBLECHECKED)) THEN - HELDOUBLECHECKED=.TRUE. - DONEHELDOUBLECHECK=.FALSE. - ENDIF - - CHECKPHASE=(NTRY.LE.CHECKCYCLE).AND.(((.NOT.FOUNDLOOPFILTER) - $ .AND.USELOOPFILTER).OR.(.NOT.FOUNDHELFILTER)) - - IF (WRITEOUTFILTERS) THEN - IF ((.NOT. CHECKPHASE).AND.(.NOT.FOUNDHELFILTER)) THEN - OPEN(1, FILE=HELFILTERFN, ERR=110, STATUS='NEW' - $ ,ACTION='WRITE') - WRITE(1,*) (GOODHEL(I),I=1,NCOMB) - 110 CONTINUE - CLOSE(1) - FOUNDHELFILTER=.TRUE. - ENDIF - - IF ((.NOT. CHECKPHASE).AND.(.NOT.FOUNDLOOPFILTER) - $ .AND.USELOOPFILTER) THEN - OPEN(1, FILE=LOOPFILTERFN, ERR=111, STATUS='NEW' - $ ,ACTION='WRITE') - DO J=1,NCOMB - WRITE(1,*) (GOODAMP(I,J),I=NCTAMPS+1,NLOOPAMPS) - ENDDO - 111 CONTINUE - CLOSE(1) - FOUNDLOOPFILTER=.TRUE. - ENDIF - ENDIF - - IF (BYPASS_CHECK) THEN - OLD_CHECKPHASE = CHECKPHASE - OLD_HELDOUBLECHECKED = HELDOUBLECHECKED - CHECKPHASE = .FALSE. - HELDOUBLECHECKED = .TRUE. - DO I=1,NCOMB - OLD_GOODHEL(I)=GOODHEL(I) - GOODHEL(I) = .TRUE. - ENDDO - DO I=1,NCOMB - DO J=1,NLOOPAMPS - OLD_GOODAMP(J,I)=GOODAMP(J,I) - GOODAMP(J,I) = .TRUE. - ENDDO - ENDDO - ENDIF - - IF(CHECKPHASE.OR.(.NOT.HELDOUBLECHECKED)) THEN - HELPICKED=1 - CTMODE=CTMODEINIT - ELSE - IF (USERHEL.NE.-1) THEN - IF(.NOT.GOODHEL(USERHEL)) THEN - ANS(1)=0.0D0 - ANS(2)=0.0D0 - ANS(3)=0.0D0 - GOTO 9999 - ENDIF - ENDIF - HELPICKED=USERHEL - IF (CTMODERUN.GT.-1) THEN - CTMODE=CTMODERUN - ELSE - CTMODE=1 - ENDIF - ENDIF - - DO I=1,NEXTERNAL - DO J=0,3 - PS(J,I)=P_USER(J,I) - ENDDO - ENDDO - - IF (IMPROVEPSPOINT.GE.0) THEN -C Make the input PS more precise (exact onshell and -C energy-momentum conservation) - CALL ML5_0_IMPROVE_PS_POINT_PRECISION(PS) - ENDIF - - DO I=1,NEXTERNAL - DO J=0,3 - P(J,I)=PS(J,I) - ENDDO - ENDDO - - DO K=1, 3 - BUFFR(K)=0.0D0 - DO I=1,NLOOPAMPS - AMPL(K,I)=(0.0D0,0.0D0) - ENDDO - ENDDO - - LSCALE=DSQRT(ABS((P(0,1)+P(0,2))**2-(P(1,1)+P(1,2))**2-(P(2,1) - $ +P(2,2))**2-(P(3,1)+P(3,2))**2)) - -C We chose to use the born evaluation for the reference - CALL ML5_0_SMATRIX(P,FLAVOR,REF) - - 200 CONTINUE - - IF (CTMODE.EQ.0.OR.CTMODE.GE.4) THEN - CALL MP_UPDATE_AS_PARAM() - ENDIF - - IF (.NOT.MP_PS_SET.AND.(CTMODE.EQ.0.OR.CTMODE.GE.4)) THEN - CALL ML5_0_SET_MP_PS(P_USER) - MP_PS_SET = .TRUE. - ENDIF - - DO K=1,3 - ANS(K)=0.0D0 - ENDDO - - VALIDH=-1 - DO H=1,NCOMB - IF ((HELPICKED.EQ.H).OR.((HELPICKED.EQ.-1) - $ .AND.(CHECKPHASE.OR.(.NOT.HELDOUBLECHECKED).OR.GOODHEL(H)))) - $ THEN - -C Handle the possible requirement of specific polarizations - IF ((.NOT.CHECKPHASE) - $ .AND.HELDOUBLECHECKED.AND.POLARIZATIONS(0,0) - $ .EQ.0.AND.(.NOT.ML5_0_IS_HEL_SELECTED(H))) THEN - CYCLE - ENDIF - - IF (VALIDH.EQ.-1) VALIDH=H - DO I=1,NEXTERNAL - NHEL(I)=HELC(I,H) - ENDDO -C Check if we are in multiple precision and compute wfs and -C amps accordingly if needed - IF (CTMODE.GE.4) THEN -C Force that only current helicity is used in the routine -C below -C This should always be done, even if MP_DONE is True -C because the AMPL of the R2 MUST be recomputed for loop -C induced. -C (because they are not saved for each hel configuration) -C (This is not optimal unlike what is done int the loop -C optimized output) - HELPICKED_BU = HELPICKED - HELPICKED = H - CALL ML5_0_MP_BORN_AMPS_AND_WFS(MP_P) - HELPICKED = HELPICKED_BU - GOTO 300 - ENDIF - CALL VXXXXX(P(0,1),ZERO,NHEL(1),-1,W(1,H)) - CALL VXXXXX(P(0,2),ZERO,NHEL(2),-1,W(2,H)) - CALL OXXXXX(P(0,3),MDL_MT,NHEL(3),+1, FLAVOR(3),W(3,H)) - CALL IXXXXX(P(0,4),MDL_MT,NHEL(4),-1, FLAVOR(4),W(4,H)) - CALL VVV1P0_1(W(1,H),W(2,H),GC_4,ZERO,ZERO,W(5,H)) -C Amplitude(s) for born diagram with ID 1 - CALL FFV1_0(W(4,H),W(3,H),W(5,H),GC_5,AMP(1,H)) - CALL FFV1_1(W(3,H),W(1,H),GC_5,MDL_MT,MDL_WT,W(6,H)) -C Amplitude(s) for born diagram with ID 2 - CALL FFV1_0(W(4,H),W(6,H),W(2,H),GC_5,AMP(2,H)) - CALL FFV1_2(W(4,H),W(1,H),GC_5,MDL_MT,MDL_WT,W(7,H)) -C Amplitude(s) for born diagram with ID 3 - CALL FFV1_0(W(7,H),W(3,H),W(2,H),GC_5,AMP(3,H)) - CALL FFV1P0_3(W(4,H),W(3,H),GC_5,ZERO,ZERO,W(8,H)) -C Counter-term amplitude(s) for loop diagram number 4 - CALL R2_GG_1_R2_GG_2_0(W(5,H),W(8,H),R2_GGG_1,R2_GGG_2 - $ ,AMPL(1,1)) -C Counter-term amplitude(s) for loop diagram number 5 - CALL FFV1_0(W(4,H),W(3,H),W(5,H),R2_GQQ,AMPL(1,2)) - CALL FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQB_1EPS,AMPL(2,3)) - CALL FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQB_1EPS,AMPL(2,4)) - CALL FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQB_1EPS,AMPL(2,5)) - CALL FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQB_1EPS,AMPL(2,6)) - CALL FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQB_1EPS,AMPL(2,7)) - CALL FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQB_1EPS,AMPL(2,8)) - CALL FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQG_1EPS,AMPL(2,9)) - CALL FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQB,AMPL(1,10)) - CALL FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQT,AMPL(1,11)) - CALL FFV1_2(W(4,H),W(2,H),GC_5,MDL_MT,MDL_WT,W(9,H)) -C Counter-term amplitude(s) for loop diagram number 7 - CALL R2_QQ_1_R2_QQ_2_0(W(9,H),W(6,H),R2_QQQ,R2_QQT,AMPL(1,12) - $ ) - CALL R2_QQ_2_0(W(9,H),W(6,H),UV_TMASS_1EPS,AMPL(2,13)) - CALL R2_QQ_2_0(W(9,H),W(6,H),UV_TMASS,AMPL(1,14)) -C Counter-term amplitude(s) for loop diagram number 8 - CALL FFV1_0(W(4,H),W(6,H),W(2,H),R2_GQQ,AMPL(1,15)) - CALL FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQB_1EPS,AMPL(2,16)) - CALL FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQB_1EPS,AMPL(2,17)) - CALL FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQB_1EPS,AMPL(2,18)) - CALL FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQB_1EPS,AMPL(2,19)) - CALL FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQB_1EPS,AMPL(2,20)) - CALL FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQB_1EPS,AMPL(2,21)) - CALL FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQG_1EPS,AMPL(2,22)) - CALL FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQB,AMPL(1,23)) - CALL FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQT,AMPL(1,24)) - CALL FFV1_1(W(3,H),W(2,H),GC_5,MDL_MT,MDL_WT,W(10,H)) -C Counter-term amplitude(s) for loop diagram number 10 - CALL R2_QQ_1_R2_QQ_2_0(W(7,H),W(10,H),R2_QQQ,R2_QQT,AMPL(1 - $ ,25)) - CALL R2_QQ_2_0(W(7,H),W(10,H),UV_TMASS_1EPS,AMPL(2,26)) - CALL R2_QQ_2_0(W(7,H),W(10,H),UV_TMASS,AMPL(1,27)) -C Counter-term amplitude(s) for loop diagram number 11 - CALL FFV1_0(W(7,H),W(3,H),W(2,H),R2_GQQ,AMPL(1,28)) - CALL FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQB_1EPS,AMPL(2,29)) - CALL FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQB_1EPS,AMPL(2,30)) - CALL FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQB_1EPS,AMPL(2,31)) - CALL FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQB_1EPS,AMPL(2,32)) - CALL FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQB_1EPS,AMPL(2,33)) - CALL FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQB_1EPS,AMPL(2,34)) - CALL FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQG_1EPS,AMPL(2,35)) - CALL FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQB,AMPL(1,36)) - CALL FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQT,AMPL(1,37)) -C Counter-term amplitude(s) for loop diagram number 13 - CALL FFV1_0(W(4,H),W(10,H),W(1,H),R2_GQQ,AMPL(1,38)) - CALL FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQB_1EPS,AMPL(2,39)) - CALL FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQB_1EPS,AMPL(2,40)) - CALL FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQB_1EPS,AMPL(2,41)) - CALL FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQB_1EPS,AMPL(2,42)) - CALL FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQB_1EPS,AMPL(2,43)) - CALL FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQB_1EPS,AMPL(2,44)) - CALL FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQG_1EPS,AMPL(2,45)) - CALL FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQB,AMPL(1,46)) - CALL FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQT,AMPL(1,47)) -C Counter-term amplitude(s) for loop diagram number 14 - CALL FFV1_0(W(9,H),W(3,H),W(1,H),R2_GQQ,AMPL(1,48)) - CALL FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQB_1EPS,AMPL(2,49)) - CALL FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQB_1EPS,AMPL(2,50)) - CALL FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQB_1EPS,AMPL(2,51)) - CALL FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQB_1EPS,AMPL(2,52)) - CALL FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQB_1EPS,AMPL(2,53)) - CALL FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQB_1EPS,AMPL(2,54)) - CALL FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQG_1EPS,AMPL(2,55)) - CALL FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQB,AMPL(1,56)) - CALL FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQT,AMPL(1,57)) -C Counter-term amplitude(s) for loop diagram number 17 - CALL VVV1_0(W(1,H),W(2,H),W(8,H),R2_3GG,AMPL(1,58)) - CALL VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GB_1EPS,AMPL(2,59)) - CALL VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GB_1EPS,AMPL(2,60)) - CALL VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GB_1EPS,AMPL(2,61)) - CALL VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GB_1EPS,AMPL(2,62)) - CALL VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GB_1EPS,AMPL(2,63)) - CALL VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GB_1EPS,AMPL(2,64)) - CALL VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GG_1EPS,AMPL(2,65)) - CALL VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GB,AMPL(1,66)) - CALL VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GT,AMPL(1,67)) -C Counter-term amplitude(s) for loop diagram number 31 - CALL R2_GG_1_0(W(5,H),W(8,H),R2_GGQ,AMPL(1,68)) - CALL R2_GG_1_0(W(5,H),W(8,H),R2_GGQ,AMPL(1,69)) - CALL R2_GG_1_0(W(5,H),W(8,H),R2_GGQ,AMPL(1,70)) - CALL R2_GG_1_0(W(5,H),W(8,H),R2_GGQ,AMPL(1,71)) -C Counter-term amplitude(s) for loop diagram number 32 - CALL VVV1_0(W(1,H),W(2,H),W(8,H),R2_3GQ,AMPL(1,72)) - CALL VVV1_0(W(1,H),W(2,H),W(8,H),R2_3GQ,AMPL(1,73)) - CALL VVV1_0(W(1,H),W(2,H),W(8,H),R2_3GQ,AMPL(1,74)) - CALL VVV1_0(W(1,H),W(2,H),W(8,H),R2_3GQ,AMPL(1,75)) -C Counter-term amplitude(s) for loop diagram number 34 - CALL R2_GG_1_R2_GG_3_0(W(5,H),W(8,H),R2_GGQ,R2_GGB,AMPL(1,76) - $ ) -C Counter-term amplitude(s) for loop diagram number 35 - CALL VVV1_0(W(1,H),W(2,H),W(8,H),R2_3GQ,AMPL(1,77)) -C Counter-term amplitude(s) for loop diagram number 37 - CALL R2_GG_1_R2_GG_3_0(W(5,H),W(8,H),R2_GGQ,R2_GGT,AMPL(1,78) - $ ) -C Counter-term amplitude(s) for loop diagram number 38 - CALL VVV1_0(W(1,H),W(2,H),W(8,H),R2_3GQ,AMPL(1,79)) -C Amplitude(s) for UVCT diagram with ID 40 - CALL FFV1_0(W(4,H),W(3,H),W(5,H),GC_5,AMPL(2,80)) - AMPL(2,80)=AMPL(2,80)*(4.0D0*UVWFCT_G_1_1EPS+2.0D0 - $ *UVWFCT_B_0_1EPS) -C Amplitude(s) for UVCT diagram with ID 41 - CALL FFV1_0(W(4,H),W(3,H),W(5,H),GC_5,AMPL(1,81)) - AMPL(1,81)=AMPL(1,81)*(2.0D0*UVWFCT_G_1+2.0D0*UVWFCT_G_2 - $ +2.0D0*UVWFCT_T_0) -C Amplitude(s) for UVCT diagram with ID 42 - CALL FFV1_0(W(4,H),W(6,H),W(2,H),GC_5,AMPL(2,82)) - AMPL(2,82)=AMPL(2,82)*(4.0D0*UVWFCT_G_1_1EPS+2.0D0 - $ *UVWFCT_B_0_1EPS) -C Amplitude(s) for UVCT diagram with ID 43 - CALL FFV1_0(W(4,H),W(6,H),W(2,H),GC_5,AMPL(1,83)) - AMPL(1,83)=AMPL(1,83)*(2.0D0*UVWFCT_G_1+2.0D0*UVWFCT_G_2 - $ +2.0D0*UVWFCT_T_0) -C Amplitude(s) for UVCT diagram with ID 44 - CALL FFV1_0(W(7,H),W(3,H),W(2,H),GC_5,AMPL(2,84)) - AMPL(2,84)=AMPL(2,84)*(4.0D0*UVWFCT_G_1_1EPS+2.0D0 - $ *UVWFCT_B_0_1EPS) -C Amplitude(s) for UVCT diagram with ID 45 - CALL FFV1_0(W(7,H),W(3,H),W(2,H),GC_5,AMPL(1,85)) - AMPL(1,85)=AMPL(1,85)*(2.0D0*UVWFCT_G_1+2.0D0*UVWFCT_G_2 - $ +2.0D0*UVWFCT_T_0) - 300 CONTINUE - - - - DO I=1,NCTAMPS - DO J=1,NBORNAMPS - CFTOT=DCMPLX(CF_N(I,J)/DBLE(ABS(CF_D(I,J))),0.0D0) - IF(CF_D(I,J).LT.0) CFTOT=CFTOT*IMAG1 - DO K=1,3 - ANS(K)=ANS(K)+2.0D0*DBLE(CFTOT*AMPL(K,I)*DCONJG(AMP(J - $ ,H))) - ENDDO - ENDDO - ENDDO - ENDIF - ENDDO - -C WHEN CTMODE IS >=4, then the MP computation of wfs and amps is -C automatically done. - IF (CTMODE.GE.4) THEN - MP_DONE = .TRUE. - ENDIF - - IF(SKIPLOOPEVAL) THEN - GOTO 1226 - ENDIF - -C Loop amplitude for loop diagram with ID 4 - CALL ML5_0_LOOP_2_2(1,5,8,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) - $ ,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4,GC_4 - $ ,MP__GC_4,2,2,1,86,AMPL(1,86),S(86)) -C Loop amplitude for loop diagram with ID 5 - CALL ML5_0_LOOP_3_3(2,3,4,5,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT - $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),DCMPLX(ZERO) - $ ,CMPLX(MP__ZERO,KIND=16),GC_5,MP__GC_5,GC_5,MP__GC_5,GC_4 - $ ,MP__GC_4,2,1,1,87,AMPL(1,87),S(87)) -C Loop amplitude for loop diagram with ID 6 - CALL ML5_0_LOOP_3_3(3,3,4,5,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) - $ ,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16),DCMPLX(MDL_MT) - $ ,CMPLX(MP__MDL_MT,KIND=16),GC_5,MP__GC_5,GC_5,MP__GC_5,GC_5 - $ ,MP__GC_5,2,1,1,88,AMPL(1,88),S(88)) -C Loop amplitude for loop diagram with ID 7 - CALL ML5_0_LOOP_2_2(4,6,9,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) - $ ,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16),GC_5,MP__GC_5,GC_5 - $ ,MP__GC_5,1,1,1,89,AMPL(1,89),S(89)) -C Loop amplitude for loop diagram with ID 8 - CALL ML5_0_LOOP_3_3(5,2,4,6,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) - $ ,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16),DCMPLX(ZERO) - $ ,CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4,GC_5,MP__GC_5,GC_5 - $ ,MP__GC_5,2,1,1,90,AMPL(1,90),S(90)) -C Loop amplitude for loop diagram with ID 9 - CALL ML5_0_LOOP_3_3(6,2,4,6,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT - $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),DCMPLX(MDL_MT) - $ ,CMPLX(MP__MDL_MT,KIND=16),GC_5,MP__GC_5,GC_5,MP__GC_5,GC_5 - $ ,MP__GC_5,2,1,1,91,AMPL(1,91),S(91)) -C Loop amplitude for loop diagram with ID 10 - CALL ML5_0_LOOP_2_2(4,10,7,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) - $ ,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16),GC_5,MP__GC_5,GC_5 - $ ,MP__GC_5,1,1,1,92,AMPL(1,92),S(92)) -C Loop amplitude for loop diagram with ID 11 - CALL ML5_0_LOOP_3_3(7,2,3,7,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) - $ ,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16),DCMPLX(ZERO) - $ ,CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4,GC_5,MP__GC_5,GC_5 - $ ,MP__GC_5,2,1,1,93,AMPL(1,93),S(93)) -C Loop amplitude for loop diagram with ID 12 - CALL ML5_0_LOOP_3_3(8,2,3,7,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT - $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),DCMPLX(MDL_MT) - $ ,CMPLX(MP__MDL_MT,KIND=16),GC_5,MP__GC_5,GC_5,MP__GC_5,GC_5 - $ ,MP__GC_5,2,1,1,94,AMPL(1,94),S(94)) -C Loop amplitude for loop diagram with ID 13 - CALL ML5_0_LOOP_3_3(5,1,4,10,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) - $ ,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16),DCMPLX(ZERO) - $ ,CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4,GC_5,MP__GC_5,GC_5 - $ ,MP__GC_5,2,1,1,95,AMPL(1,95),S(95)) -C Loop amplitude for loop diagram with ID 14 - CALL ML5_0_LOOP_3_3(7,1,3,9,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) - $ ,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16),DCMPLX(ZERO) - $ ,CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4,GC_5,MP__GC_5,GC_5 - $ ,MP__GC_5,2,1,1,96,AMPL(1,96),S(96)) -C Loop amplitude for loop diagram with ID 15 - CALL ML5_0_LOOP_4_4(9,1,2,4,3,DCMPLX(ZERO),CMPLX(MP__ZERO - $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),DCMPLX(MDL_MT) - $ ,CMPLX(MP__MDL_MT,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) - $ ,GC_4,MP__GC_4,GC_4,MP__GC_4,GC_5,MP__GC_5,GC_5,MP__GC_5,3,1,1 - $ ,97,AMPL(1,97),S(97)) -C Loop amplitude for loop diagram with ID 16 - CALL ML5_0_LOOP_4_4(10,1,2,3,4,DCMPLX(ZERO),CMPLX(MP__ZERO - $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),DCMPLX(MDL_MT) - $ ,CMPLX(MP__MDL_MT,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) - $ ,GC_4,MP__GC_4,GC_4,MP__GC_4,GC_5,MP__GC_5,GC_5,MP__GC_5,3,1,1 - $ ,98,AMPL(1,98),S(98)) -C Loop amplitude for loop diagram with ID 17 - CALL ML5_0_LOOP_3_3(11,1,2,8,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) - $ ,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),DCMPLX(ZERO) - $ ,CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4,GC_4,MP__GC_4,GC_4 - $ ,MP__GC_4,3,1,1,99,AMPL(1,99),S(99)) -C Loop amplitude for loop diagram with ID 18 - CALL ML5_0_LOOP_2_3_2(12,1,2,1,8,2,DCMPLX(ZERO),CMPLX(MP__ZERO - $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4 - $ ,GC_6,MP__GC_6,1,2,1,100,AMPL(1,100),S(100)) - CALL ML5_0_LOOP_2_3_2(13,1,2,1,8,2,DCMPLX(ZERO),CMPLX(MP__ZERO - $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4 - $ ,GC_6,MP__GC_6,1,2,1,101,AMPL(1,101),S(101)) - CALL ML5_0_LOOP_2_3_2(14,1,2,1,8,2,DCMPLX(ZERO),CMPLX(MP__ZERO - $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4 - $ ,GC_6,MP__GC_6,1,2,1,102,AMPL(1,102),S(102)) -C Loop amplitude for loop diagram with ID 19 - CALL ML5_0_LOOP_4_4(15,1,3,2,4,DCMPLX(ZERO),CMPLX(MP__ZERO - $ ,KIND=16),DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16) - $ ,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16),DCMPLX(ZERO) - $ ,CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4,GC_5,MP__GC_5,GC_5 - $ ,MP__GC_5,GC_5,MP__GC_5,3,1,1,103,AMPL(1,103),S(103)) -C Loop amplitude for loop diagram with ID 20 - CALL ML5_0_LOOP_3_3(6,1,4,10,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT - $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),DCMPLX(MDL_MT) - $ ,CMPLX(MP__MDL_MT,KIND=16),GC_5,MP__GC_5,GC_5,MP__GC_5,GC_5 - $ ,MP__GC_5,2,1,1,104,AMPL(1,104),S(104)) -C Loop amplitude for loop diagram with ID 21 - CALL ML5_0_LOOP_3_3(8,1,3,9,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT - $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),DCMPLX(MDL_MT) - $ ,CMPLX(MP__MDL_MT,KIND=16),GC_5,MP__GC_5,GC_5,MP__GC_5,GC_5 - $ ,MP__GC_5,2,1,1,105,AMPL(1,105),S(105)) -C Loop amplitude for loop diagram with ID 22 - CALL ML5_0_LOOP_2_3_2(12,1,2,2,8,1,DCMPLX(ZERO),CMPLX(MP__ZERO - $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4 - $ ,GC_6,MP__GC_6,1,2,1,106,AMPL(1,106),S(106)) - CALL ML5_0_LOOP_2_3_2(13,1,2,2,8,1,DCMPLX(ZERO),CMPLX(MP__ZERO - $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4 - $ ,GC_6,MP__GC_6,1,2,1,107,AMPL(1,107),S(107)) - CALL ML5_0_LOOP_2_3_2(14,1,2,2,8,1,DCMPLX(ZERO),CMPLX(MP__ZERO - $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4 - $ ,GC_6,MP__GC_6,1,2,1,108,AMPL(1,108),S(108)) -C Loop amplitude for loop diagram with ID 23 - CALL ML5_0_LOOP_4_4(16,1,3,2,4,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT - $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),DCMPLX(ZERO) - $ ,CMPLX(MP__ZERO,KIND=16),DCMPLX(MDL_MT),CMPLX(MP__MDL_MT - $ ,KIND=16),GC_5,MP__GC_5,GC_5,MP__GC_5,GC_4,MP__GC_4,GC_5 - $ ,MP__GC_5,3,1,1,109,AMPL(1,109),S(109)) -C Loop amplitude for loop diagram with ID 24 - CALL ML5_0_LOOP_4_4(17,1,2,4,3,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT - $ ,KIND=16),DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16),DCMPLX(ZERO) - $ ,CMPLX(MP__ZERO,KIND=16),DCMPLX(MDL_MT),CMPLX(MP__MDL_MT - $ ,KIND=16),GC_5,MP__GC_5,GC_5,MP__GC_5,GC_5,MP__GC_5,GC_5 - $ ,MP__GC_5,3,1,1,110,AMPL(1,110),S(110)) -C Loop amplitude for loop diagram with ID 25 - CALL ML5_0_LOOP_4_4(18,1,2,3,4,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT - $ ,KIND=16),DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16),DCMPLX(ZERO) - $ ,CMPLX(MP__ZERO,KIND=16),DCMPLX(MDL_MT),CMPLX(MP__MDL_MT - $ ,KIND=16),GC_5,MP__GC_5,GC_5,MP__GC_5,GC_5,MP__GC_5,GC_5 - $ ,MP__GC_5,3,1,1,111,AMPL(1,111),S(111)) -C Loop amplitude for loop diagram with ID 26 - CALL ML5_0_LOOP_2_3_2(19,2,1,2,1,8,DCMPLX(ZERO),CMPLX(MP__ZERO - $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_6,MP__GC_6 - $ ,GC_4,MP__GC_4,1,2,1,112,AMPL(1,112),S(112)) - CALL ML5_0_LOOP_2_3_2(20,2,1,2,1,8,DCMPLX(ZERO),CMPLX(MP__ZERO - $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_6,MP__GC_6 - $ ,GC_4,MP__GC_4,1,2,1,113,AMPL(1,113),S(113)) - CALL ML5_0_LOOP_2_3_2(21,2,1,2,1,8,DCMPLX(ZERO),CMPLX(MP__ZERO - $ ,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_6,MP__GC_6 - $ ,GC_4,MP__GC_4,1,2,1,114,AMPL(1,114),S(114)) -C Loop amplitude for loop diagram with ID 27 - CALL ML5_0_LOOP_3_4_3(22,1,1,2,3,4,2,1,DCMPLX(MDL_MT) - $ ,CMPLX(MP__MDL_MT,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) - $ ,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_5,MP__GC_5,GC_5 - $ ,MP__GC_5,GC_6,MP__GC_6,1,1,1,115,AMPL(1,115),S(115)) - CALL ML5_0_LOOP_3_4_3(23,1,1,2,3,4,2,1,DCMPLX(MDL_MT) - $ ,CMPLX(MP__MDL_MT,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) - $ ,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_5,MP__GC_5,GC_5 - $ ,MP__GC_5,GC_6,MP__GC_6,1,1,1,116,AMPL(1,116),S(116)) - CALL ML5_0_LOOP_3_4_3(24,1,1,2,3,4,2,1,DCMPLX(MDL_MT) - $ ,CMPLX(MP__MDL_MT,KIND=16),DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) - $ ,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_5,MP__GC_5,GC_5 - $ ,MP__GC_5,GC_6,MP__GC_6,1,1,1,117,AMPL(1,117),S(117)) -C Loop amplitude for loop diagram with ID 28 - CALL ML5_0_LOOP_2_2(25,5,8,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) - $ ,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4,GC_4 - $ ,MP__GC_4,2,1,1,118,AMPL(1,118),S(118)) -C Loop amplitude for loop diagram with ID 29 - CALL ML5_0_LOOP_3_3(26,1,2,8,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) - $ ,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),DCMPLX(ZERO) - $ ,CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4,GC_4,MP__GC_4,GC_4 - $ ,MP__GC_4,3,1,1,119,AMPL(1,119),S(119)) -C Loop amplitude for loop diagram with ID 30 - CALL ML5_0_LOOP_3_3(27,1,2,8,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) - $ ,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),DCMPLX(ZERO) - $ ,CMPLX(MP__ZERO,KIND=16),GC_4,MP__GC_4,GC_4,MP__GC_4,GC_4 - $ ,MP__GC_4,3,1,1,120,AMPL(1,120),S(120)) -C Loop amplitude for loop diagram with ID 31 - CALL ML5_0_LOOP_2_2(28,5,8,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) - $ ,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),GC_5,MP__GC_5,GC_5 - $ ,MP__GC_5,2,1,4,121,AMPL(1,121),S(121)) -C Loop amplitude for loop diagram with ID 32 - CALL ML5_0_LOOP_3_3(29,1,2,8,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) - $ ,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),DCMPLX(ZERO) - $ ,CMPLX(MP__ZERO,KIND=16),GC_5,MP__GC_5,GC_5,MP__GC_5,GC_5 - $ ,MP__GC_5,3,1,4,122,AMPL(1,122),S(122)) -C Loop amplitude for loop diagram with ID 33 - CALL ML5_0_LOOP_3_3(30,1,2,8,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16) - $ ,DCMPLX(ZERO),CMPLX(MP__ZERO,KIND=16),DCMPLX(ZERO) - $ ,CMPLX(MP__ZERO,KIND=16),GC_5,MP__GC_5,GC_5,MP__GC_5,GC_5 - $ ,MP__GC_5,3,1,4,123,AMPL(1,123),S(123)) -C Loop amplitude for loop diagram with ID 34 - CALL ML5_0_LOOP_2_2(28,5,8,DCMPLX(MDL_MB),CMPLX(MP__MDL_MB - $ ,KIND=16),DCMPLX(MDL_MB),CMPLX(MP__MDL_MB,KIND=16),GC_5 - $ ,MP__GC_5,GC_5,MP__GC_5,2,1,1,124,AMPL(1,124),S(124)) -C Loop amplitude for loop diagram with ID 35 - CALL ML5_0_LOOP_3_3(29,1,2,8,DCMPLX(MDL_MB),CMPLX(MP__MDL_MB - $ ,KIND=16),DCMPLX(MDL_MB),CMPLX(MP__MDL_MB,KIND=16) - $ ,DCMPLX(MDL_MB),CMPLX(MP__MDL_MB,KIND=16),GC_5,MP__GC_5,GC_5 - $ ,MP__GC_5,GC_5,MP__GC_5,3,1,1,125,AMPL(1,125),S(125)) -C Loop amplitude for loop diagram with ID 36 - CALL ML5_0_LOOP_3_3(30,1,2,8,DCMPLX(MDL_MB),CMPLX(MP__MDL_MB - $ ,KIND=16),DCMPLX(MDL_MB),CMPLX(MP__MDL_MB,KIND=16) - $ ,DCMPLX(MDL_MB),CMPLX(MP__MDL_MB,KIND=16),GC_5,MP__GC_5,GC_5 - $ ,MP__GC_5,GC_5,MP__GC_5,3,1,1,126,AMPL(1,126),S(126)) -C Loop amplitude for loop diagram with ID 37 - CALL ML5_0_LOOP_2_2(28,5,8,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT - $ ,KIND=16),DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16),GC_5 - $ ,MP__GC_5,GC_5,MP__GC_5,2,1,1,127,AMPL(1,127),S(127)) -C Loop amplitude for loop diagram with ID 38 - CALL ML5_0_LOOP_3_3(29,1,2,8,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT - $ ,KIND=16),DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16) - $ ,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16),GC_5,MP__GC_5,GC_5 - $ ,MP__GC_5,GC_5,MP__GC_5,3,1,1,128,AMPL(1,128),S(128)) -C Loop amplitude for loop diagram with ID 39 - CALL ML5_0_LOOP_3_3(30,1,2,8,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT - $ ,KIND=16),DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16) - $ ,DCMPLX(MDL_MT),CMPLX(MP__MDL_MT,KIND=16),GC_5,MP__GC_5,GC_5 - $ ,MP__GC_5,GC_5,MP__GC_5,3,1,1,129,AMPL(1,129),S(129)) - - DO I=NCTAMPS+1,NLOOPAMPS - ANS(1)=ANS(1)+AMPL(1,I) - ANS(2)=ANS(2)+AMPL(2,I) - ANS(3)=ANS(3)+AMPL(3,I) - IF((CTMODERUN.NE.-1).AND..NOT.CHECKPHASE.AND.(.NOT.S(I))) THEN - WRITE(*,*) '##W03 WARNING Contribution ',I,' is unstable.' - ENDIF - ENDDO - - 1226 CONTINUE - - IF (CHECKPHASE.OR.(.NOT.HELDOUBLECHECKED)) THEN -C Update of NEXTREF, will be used for loop induced only. - NEXTREF = NEXTREF + ANS(1) + ANS(2) + ANS(3) - IF((USERHEL.EQ.-1).OR.(USERHEL.EQ.HELPICKED)) THEN - BUFFR(1)=BUFFR(1)+ANS(1) - BUFFR(2)=BUFFR(2)+ANS(2) - BUFFR(3)=BUFFR(3)+ANS(3) - ENDIF - - IF (CHECKPHASE) THEN -C SET THE HELICITY FILTER - IF(.NOT.FOUNDHELFILTER) THEN - IF(ML5_0_ISZERO(ABS(ANS(1))+ABS(ANS(2))+ABS(ANS(3)),REF - $ /DBLE(NCOMB),-1)) THEN - IF(NTRY.EQ.1) THEN - GOODHEL(HELPICKED)=.FALSE. - ELSEIF(GOODHEL(HELPICKED)) THEN - WRITE(*,*) '##W02A WARNING Inconsistent helicity ' - $ ,HELPICKED - IF(HELINITSTARTOVER) THEN - WRITE(*,*) '##I01 INFO Initialization starting over' - $ //' because of inconsistency in the helicity filter' - $ //' setup.' - NTRY=0 - ENDIF - ENDIF - ELSE - IF(.NOT.GOODHEL(HELPICKED)) THEN - WRITE(*,*) '##W02B WARNING Inconsistent helicity ' - $ ,HELPICKED - IF(HELINITSTARTOVER) THEN - WRITE(*,*) '##I01 INFO Initialization starting over' - $ //' because of inconsistency in the helicity filter' - $ //' setup.' - NTRY=0 - ELSE - GOODHEL(HELPICKED)=.TRUE. - ENDIF - ENDIF - ENDIF - ENDIF - -C SET THE LOOP FILTER - IF(.NOT.FOUNDLOOPFILTER.AND.USELOOPFILTER) THEN - DO I=NCTAMPS+1,NLOOPAMPS - IF(.NOT.ML5_0_ISZERO(ABS(AMPL(1,I))+ABS(AMPL(2,I)) - $ +ABS(AMPL(3,I)),(REF*1.0D-4),I)) THEN - IF(NTRY.EQ.1) THEN - GOODAMP(I,HELPICKED)=.TRUE. - ELSEIF(.NOT.GOODAMP(I,HELPICKED)) THEN - WRITE(*,*) '##W02 WARNING Inconsistent loop amp ',I - $ ,' for helicity ',HELPICKED,'.' - IF(LOOPINITSTARTOVER) THEN - WRITE(*,*) '##I01 INFO Initialization starting' - $ //' over because of inconsistency in the loop' - $ //' filter setup.' - NTRY=0 - ELSE - GOODAMP(I,HELPICKED)=.TRUE. - ENDIF - ENDIF - ENDIF - ENDDO - ENDIF - ELSEIF (.NOT.HELDOUBLECHECKED)THEN - IF ((.NOT.GOODHEL(HELPICKED)) - $ .AND.(.NOT.ML5_0_ISZERO(ABS(ANS(1))+ABS(ANS(2))+ABS(ANS(3)) - $ ,REF/DBLE(NCOMB),-1))) THEN - WRITE(*,*) '##W15 Helicity filter could not be' - $ //' successfully double checked.' - WRITE(*,*) '##One reason for this is that you have changed' - $ //' sensible parameters which affected what are the zero' - $ //' helicity configurations.' - WRITE(*,*) '##MadLoop will try to reset the Helicity' - $ //' filter with the next PS points it receives.' - NTRY=0 - OPEN(30,FILE=HELFILTERFN,ERR=349) - 349 CONTINUE - CLOSE(30,STATUS='delete') - ENDIF -C SET HELDOUBLECHECKED TO .TRUE. WHEN DONE -C even if it failed we do not want to redo the check -C afterwards if HELINITSTARTOVER=.FALSE. - IF (HELPICKED.EQ.NCOMB.AND.(NTRY.NE.0.OR..NOT.HELINITSTARTOVE - $R)) THEN - DONEHELDOUBLECHECK=.TRUE. - ENDIF - ENDIF - -C GOTO NEXT HELICITY OR FINISH - IF(HELPICKED.NE.NCOMB) THEN - HELPICKED=HELPICKED+1 - MP_DONE=.FALSE. - GOTO 200 - ELSE - ANS(1)=BUFFR(1) - ANS(2)=BUFFR(2) - ANS(3)=BUFFR(3) -C We add one here to the number of PS points used for building -C the reference scale for comparison (used only for -C loop-induced processes). - NPSPOINTS = NPSPOINTS+1 - IF(NTRY.EQ.0) THEN - NATTEMPTS=NATTEMPTS+1 - IF(NATTEMPTS.EQ.MAXATTEMPTS) THEN - WRITE(*,*) '##E01 ERROR Could not initialize the filters' - $ //' in ',MAXATTEMPTS,' trials' - STOP - ENDIF - ENDIF - ENDIF - - ENDIF - - DO K=1,3 - ANS(K)=ANS(K)/DBLE(IDEN) - IF (USERHEL.NE.-1) THEN - ANS(K)=ANS(K)*HELAVGFACTOR - ELSE - DO J=1,NINITIAL - IF (POLARIZATIONS(J,0).NE.-1) THEN - ANS(K)=ANS(K)*BEAMS_HELAVGFACTOR(J) - ANS(K)=ANS(K)/POLARIZATIONS(J,0) - ENDIF - ENDDO - ENDIF - ENDDO - - IF(.NOT.CHECKPHASE.AND.HELDOUBLECHECKED.AND.(CTMODERUN.LE.-1)) - $ THEN - STAB_INDEX=STAB_INDEX+1 - IF(DOING_QP_EVALS) THEN - QP_RES(1,STAB_INDEX)=ANS(1) - QP_RES(2,STAB_INDEX)=ANS(2) - QP_RES(3,STAB_INDEX)=ANS(3) - ELSE - DP_RES(1,STAB_INDEX)=ANS(1) - DP_RES(2,STAB_INDEX)=ANS(2) - DP_RES(3,STAB_INDEX)=ANS(3) - ENDIF - - IF(DOING_QP_EVALS) THEN - BASIC_CT_MODE=4 - ELSE - BASIC_CT_MODE=1 - ENDIF - -C BEGINNING OF THE DEFINITIONS OF THE DIFFERENT EVALUATION -C METHODS - - IF(.NOT.EVAL_DONE(2)) THEN - EVAL_DONE(2)=.TRUE. - CTMODE=BASIC_CT_MODE+1 - GOTO 200 - ENDIF - - CTMODE=BASIC_CT_MODE - - IF(.NOT.EVAL_DONE(3).AND. - $ ((DOING_QP_EVALS.AND.NROTATIONS_QP.GE.1) - $ .OR.((.NOT.DOING_QP_EVALS).AND.NROTATIONS_DP.GE.1)) ) THEN - EVAL_DONE(3)=.TRUE. - CALL ML5_0_ROTATE_PS(PS,P,1) - IF (DOING_QP_EVALS) CALL ML5_0_MP_ROTATE_PS(MP_PS,MP_P,1) - GOTO 200 - ENDIF - - IF(.NOT.EVAL_DONE(4).AND. - $ ((DOING_QP_EVALS.AND.NROTATIONS_QP.GE.2) - $ .OR.((.NOT.DOING_QP_EVALS).AND.NROTATIONS_DP.GE.2)) ) THEN - EVAL_DONE(4)=.TRUE. - CALL ML5_0_ROTATE_PS(PS,P,2) - IF (DOING_QP_EVALS) CALL ML5_0_MP_ROTATE_PS(MP_PS,MP_P,2) - GOTO 200 - ENDIF - - CALL ML5_0_ROTATE_PS(PS,P,0) - IF (DOING_QP_EVALS) CALL ML5_0_MP_ROTATE_PS(MP_PS,MP_P,0) - -C END OF THE DEFINITIONS OF THE DIFFERENT EVALUATION METHODS - - IF(DOING_QP_EVALS) THEN - CALL ML5_0_COMPUTE_ACCURACY(QP_RES,N_QP_EVAL,ACC,ANS(1)) - ACCURACY(0)=ACC - RET_CODE_H=3 - IF(ACC.GE.MLSTABTHRES) THEN - RET_CODE_H=4 - NEPS=NEPS+1 - CALL ML5_0_COMPUTE_ACCURACY(DP_RES,N_DP_EVAL,TEMP1,TEMP) - WRITE(*,*) '##W03 WARNING An unstable PS point was', - $ ' detected.' - WRITE(*,*) '##(DP,QP) accuracies : (',TEMP1,',',ACC,')' - WRITE(*,*) '##Best estimate (fin,1eps,2eps) :',(ANS(I),I=1 - $ ,3) - IF(NEPS.LE.10) THEN - WRITE(*,*) '##Double precision evaluations :',(DP_RES(1 - $ ,I),I=1,N_DP_EVAL) - WRITE(*,*) '##Quad precision evaluations :',(QP_RES(1 - $ ,I),I=1,N_QP_EVAL) - WRITE(*,*) '##PS point specification :' - WRITE(*,*) '##Renormalization scale MU_R=',MU_R - DO I=1,NEXTERNAL - WRITE (*,'(i2,1x,4e27.17)') I, P(0,I),P(1,I),P(2,I) - $ ,P(3,I) - ENDDO - ENDIF - IF(NEPS.EQ.10) THEN - WRITE(*,*) '##Further output of the details of these' - $ //' unstable PS points will now be suppressed.' - ENDIF - ENDIF - ELSE - CALL ML5_0_COMPUTE_ACCURACY(DP_RES,N_DP_EVAL,ACC,ANS(1)) - IF(ACC.GE.MLSTABTHRES) THEN - DOING_QP_EVALS=.TRUE. - EVAL_DONE(1)=.TRUE. - DO I=2,MAXSTABILITYLENGTH - EVAL_DONE(I)=.FALSE. - ENDDO - STAB_INDEX=0 - CTMODE=4 - GOTO 200 - ELSE - ACCURACY(0)=ACC - RET_CODE_H=2 - ENDIF - ENDIF - ELSE - RET_CODE_H=1 - ACCURACY=-1.0D0 - ENDIF - - 9999 CONTINUE - -C Finalize the return code - IF (MP_DONE_ONCE) THEN - RET_CODE_T=2 - ELSE - RET_CODE_T=1 - ENDIF - IF(CHECKPHASE.OR..NOT.HELDOUBLECHECKED) THEN - RET_CODE_H=1 - RET_CODE_T=RET_CODE_T+2 - ACCURACY=-1.0D0 - ENDIF - IF (RET_CODE_H.EQ.4) THEN - RET_CODE_U=0 - ELSE - RET_CODE_U=1 - ENDIF - -C Reinitialize the default threshold if it was specified by the -C user - IF (USER_STAB_PREC.GT.0.0D0) THEN - MLSTABTHRES=MLSTABTHRES_BU - CTMODEINIT=CTMODEINIT_BU - ENDIF - -C Reinitialize the Lorentz test if it had been disabled because -C spin-2 particles are in the external states. - NROTATIONS_DP = NROTATIONS_DP_BU - NROTATIONS_QP = NROTATIONS_QP_BU - -C Conform to the returned synthax of split orders even though the -C default output does not support it (this then done only for -C compatibility purpose). - ANSRETURNED(0,0)=ANS(0) - ANSRETURNED(1,0)=ANS(1) - ANSRETURNED(2,0)=ANS(2) - ANSRETURNED(3,0)=ANS(3) - -C Reinitialize the check phase logicals and the filters if check -C bypassed - IF (BYPASS_CHECK) THEN - CHECKPHASE = OLD_CHECKPHASE - HELDOUBLECHECKED = OLD_HELDOUBLECHECKED - DO I=1,NCOMB - GOODHEL(I)=OLD_GOODHEL(I) - ENDDO - DO I=1,NCOMB - DO J=1,NLOOPAMPS - GOODAMP(J,I)=OLD_GOODAMP(J,I) - ENDDO - ENDDO - ENDIF - - END - - SUBROUTINE ML5_0_COMPUTE_ACCURACY(FULLLIST, LENGTH, ACC, - $ ESTIMATE) - IMPLICIT NONE -C -C PARAMETERS -C - INTEGER MAXSTABILITYLENGTH - COMMON/ML5_0_STABILITY_TESTS/MAXSTABILITYLENGTH -C -C ARGUMENTS -C - REAL*8 FULLLIST(3,MAXSTABILITYLENGTH) - INTEGER LENGTH - REAL*8 ACC, ESTIMATE(3) -C -C LOCAL VARIABLES -C - LOGICAL MASK(MAXSTABILITYLENGTH) - LOGICAL MASK3(3) - DATA MASK3/.TRUE.,.TRUE.,.TRUE./ - INTEGER I,J - REAL*8 AVG - REAL*8 DIFF - REAL*8 ACCURACIES(3) - REAL*8 LIST(MAXSTABILITYLENGTH) - -C ---------- -C BEGIN CODE -C ---------- - DO I=1,LENGTH - MASK(I)=.TRUE. - ENDDO - DO I=LENGTH+1,MAXSTABILITYLENGTH - MASK(I)=.FALSE. - ENDDO - - DO I=1,3 - DO J=1,MAXSTABILITYLENGTH - LIST(J)=FULLLIST(I,J) - ENDDO - DIFF=MAXVAL(LIST,1,MASK)-MINVAL(LIST,1,MASK) - AVG=(MAXVAL(LIST,1,MASK)+MINVAL(LIST,1,MASK))/2.0D0 - ESTIMATE(I)=AVG - IF (AVG.EQ.0.0D0) THEN - ACCURACIES(I)=DIFF - ELSE - ACCURACIES(I)=DIFF/ABS(AVG) - ENDIF - ENDDO - -C The technique below is too sensitive, typically to -C unstablities in very small poles -C ACC=MAXVAL(ACCURACIES,1,MASK3) -C The following is used instead - ACC = 0.0D0 - AVG = 0.0D0 - DO I=1,3 - ACC = ACC + ACCURACIES(I)*ABS(ESTIMATE(I)) - AVG = AVG + ESTIMATE(I) - ENDDO - ACC = ACC / ( ABS(AVG) / 3.0D0) - -C If NaN are present in the evaluation, automatically set the -C accuracy to 1.0d99. - DO I=1,3 - DO J=1,MAXSTABILITYLENGTH - IF (ISNAN(FULLLIST(I,J))) THEN - ACC = 1.0D99 - ENDIF - ENDDO - ENDDO - - END - - SUBROUTINE ML5_0_SET_N_EVALS(N_DP_EVALS,N_QP_EVALS) - - IMPLICIT NONE - INTEGER N_DP_EVALS, N_QP_EVALS - - INCLUDE 'MadLoopParams.inc' - - IF(CTMODERUN.LE.-1) THEN - N_DP_EVALS=2+NROTATIONS_DP - N_QP_EVALS=2+NROTATIONS_QP - ELSE - N_DP_EVALS=1 - N_QP_EVALS=1 - ENDIF - - IF(N_DP_EVALS.GT.20.OR.N_QP_EVALS.GT.20) THEN - WRITE(*,*) '##ERROR:: Increase hardcoded maxstabilitylength.' - STOP - ENDIF - - END - - -C THIS SUBROUTINE SIMPLY SET THE GLOBAL PS CONFIGURATION GLOBAL -C VARIABLES FROM A GIVEN VARIABLE IN DOUBLE PRECISION - SUBROUTINE ML5_0_SET_MP_PS(P) - - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - REAL*16 MP_PS(0:3,NEXTERNAL),MP_P(0:3,NEXTERNAL) - COMMON/ML5_0_MP_PSPOINT/MP_PS,MP_P - REAL*8 P(0:3,NEXTERNAL) - - DO I=1,NEXTERNAL - DO J=0,3 - MP_PS(J,I)=P(J,I) - ENDDO - ENDDO - CALL ML5_0_MP_IMPROVE_PS_POINT_PRECISION(MP_PS) - DO I=1,NEXTERNAL - DO J=0,3 - MP_P(J,I)=MP_PS(J,I) - ENDDO - ENDDO - - END - - SUBROUTINE ML5_0_SET_COUPLINGORDERS_TARGET(SOTARGET) - IMPLICIT NONE -C -C This routine can be accessed by an external user to set the -C squared split order target. -C This functionality is only available in the optimized mode, but -C for compatibility -C purposes, a dummy version is also put in this default output. -C -C -C ARGUMENTS -C - INTEGER SOTARGET -C ---------- -C BEGIN CODE -C ---------- - WRITE(*,*) '##WARNING:: Ignored, the possibility of selecting' - $ //' specific squared order contributions is not available in' - $ //' the default mode.' - - END - - SUBROUTINE ML5_0_FORCE_STABILITY_CHECK(ONOFF) -C -C This function can be called by the MadLoop user so as to always -C have stability -C checked, even during initialisation, when calling the *_thres -C routines. -C - LOGICAL ONOFF - - LOGICAL BYPASS_CHECK, ALWAYS_TEST_STABILITY - DATA BYPASS_CHECK, ALWAYS_TEST_STABILITY /.FALSE.,.FALSE./ - COMMON/ML5_0_BYPASS_CHECK/BYPASS_CHECK, ALWAYS_TEST_STABILITY - - ALWAYS_TEST_STABILITY = ONOFF - - END - - SUBROUTINE ML5_0_GET_ANSWER_DIMENSION(ANSDIM) -C -C Simple subroutine which returns the upper bound of the second -C dimension of the -C quantity ANS(0:3,0:ANSDIM) returned by MadLoop. As long as the -C default output -C cannot handle split orders, this ANSDIM will always be 0. -C - INCLUDE 'nsquaredSO.inc' - - INTEGER ANSDIM - - ANSDIM=NSQUAREDSO - - END - - SUBROUTINE ML5_0_GET_NSQSO_LOOP(NSQSO) -C -C Simple subroutine returning the number of squared split order -C contributions returned in ANS when calling sloopmatrix -C - INCLUDE 'nsquaredSO.inc' - - INTEGER NSQSO - - NSQSO=NSQUAREDSO - - END - - SUBROUTINE ML5_0_SET_LEG_POLARIZATION(LEG_ID, LEG_POLARIZATION) - IMPLICIT NONE -C -C ARGUMENTS -C - INTEGER LEG_ID - INTEGER LEG_POLARIZATION -C -C LOCALS -C - INTEGER I - INTEGER LEG_POLARIZATIONS(0:5) -C ---------- -C BEGIN CODE -C ---------- - - IF (LEG_POLARIZATION.EQ.-10000) THEN - LEG_POLARIZATIONS(0)=-1 - DO I=1,5 - LEG_POLARIZATIONS(I)=-10000 - ENDDO - ELSE - LEG_POLARIZATIONS(0)=1 - LEG_POLARIZATIONS(1)=LEG_POLARIZATION - DO I=2,5 - LEG_POLARIZATIONS(I)=-10000 - ENDDO - ENDIF - CALL ML5_0_SET_LEG_POLARIZATIONS(LEG_ID,LEG_POLARIZATIONS) - - END - - SUBROUTINE ML5_0_SET_LEG_POLARIZATIONS(LEG_ID, LEG_POLARIZATIONS) - IMPLICIT NONE -C -C CONSTANTS -C - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INTEGER NPOLENTRIES - PARAMETER (NPOLENTRIES=(NEXTERNAL+1)*6) - INTEGER NCOMB - PARAMETER (NCOMB=16) -C -C ARGUMENTS -C - INTEGER LEG_ID - INTEGER LEG_POLARIZATIONS(0:5) -C -C LOCALS -C - INTEGER I,J - LOGICAL ALL_SUMMED_OVER -C -C GLOBALS -C -C Entry 0 of the first dimension is all -1 if there is no -C polarization requirement. -C Then for each leg with ID legID, it is either summed over if -C POLARIZATIONS(legID,0) is -1, or the list of helicity considered -C for that -C leg is POLARIZATIONS(legID,1: POLARIZATIONS(legID,0) ). - INTEGER POLARIZATIONS(0:NEXTERNAL,0:5) - DATA ((POLARIZATIONS(I,J),I=0,NEXTERNAL),J=0,5)/NPOLENTRIES*-1/ - COMMON/ML5_0_BEAM_POL/POLARIZATIONS - - INTEGER BORN_POLARIZATIONS(0:NEXTERNAL,0:5) - COMMON/ML5_0_BORN_BEAM_POL/BORN_POLARIZATIONS - -C ---------- -C BEGIN CODE -C ---------- - - IF (LEG_POLARIZATIONS(0).EQ.-1) THEN - DO I=0,5 - POLARIZATIONS(LEG_ID,I)=-1 - ENDDO - ELSE - DO I=0,LEG_POLARIZATIONS(0) - POLARIZATIONS(LEG_ID,I)=LEG_POLARIZATIONS(I) - ENDDO - DO I=LEG_POLARIZATIONS(0)+1,5 - POLARIZATIONS(LEG_ID,I)=-10000 - ENDDO - ENDIF - - ALL_SUMMED_OVER = .TRUE. - DO I=1,NEXTERNAL - IF (POLARIZATIONS(I,0).NE.-1) THEN - ALL_SUMMED_OVER = .FALSE. - EXIT - ENDIF - ENDDO - IF (ALL_SUMMED_OVER) THEN - DO I=0,5 - POLARIZATIONS(0,I)=-1 - ENDDO - ELSE - DO I=0,5 - POLARIZATIONS(0,I)=0 - ENDDO - ENDIF - - DO I=0,NEXTERNAL - DO J=0,5 - BORN_POLARIZATIONS(I,J) = POLARIZATIONS(I,J) - ENDDO - ENDDO - - - RETURN - - END - - SUBROUTINE ML5_0_SLOOPMATRIXHEL_THRES(P,HEL,ANS,PREC_ASKED - $ ,PREC_FOUND,RET_CODE) - IMPLICIT NONE -C -C CONSTANTS -C - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INCLUDE 'nsquaredSO.inc' -C -C ARGUMENTS -C - REAL*8 P(0:3,NEXTERNAL) - REAL*8 ANS(0:3,0:NSQUAREDSO) - INTEGER HEL,RET_CODE - REAL*8 PREC_ASKED,PREC_FOUND(0:NSQUAREDSO) -C -C GLOBAL VARIABLES -C - REAL*8 USER_STAB_PREC - COMMON/ML5_0_USER_STAB_PREC/USER_STAB_PREC - - INTEGER I - - INTEGER H,T,U - REAL*8 ACCURACY(0:NSQUAREDSO) - COMMON/ML5_0_ACC/ACCURACY,H,T,U - - LOGICAL BYPASS_CHECK, ALWAYS_TEST_STABILITY - COMMON/ML5_0_BYPASS_CHECK/BYPASS_CHECK, ALWAYS_TEST_STABILITY - -C ---------- -C BEGIN CODE -C ---------- - USER_STAB_PREC = PREC_ASKED - CALL ML5_0_SLOOPMATRIXHEL(P,HEL,ANS) - IF(ALWAYS_TEST_STABILITY.AND.(H.EQ.1.OR.ACCURACY(0).LT.0.0D0)) - $ THEN - BYPASS_CHECK = .TRUE. - CALL ML5_0_SLOOPMATRIXHEL(P,HEL,ANS) - BYPASS_CHECK = .FALSE. -C Make sure we correctly return an initialization-type T code - IF (T.EQ.2) T=4 - IF (T.EQ.1) T=3 - ENDIF - -C Reset it to default value not to affect next runs - USER_STAB_PREC = -1.0D0 - DO I=0,NSQUAREDSO - PREC_FOUND(I)=ACCURACY(I) - ENDDO - RET_CODE=100*H+10*T+U - - END - - SUBROUTINE ML5_0_SLOOPMATRIX_THRES(P,ANS,PREC_ASKED,PREC_FOUND - $ ,RET_CODE) -C -C Inputs are: -C P(0:3, Nexternal) double :: Kinematic configuration -C (E,px,py,pz) -C PEC_ASKED double :: Target relative accuracy, -1 for -C default -C -C Outputs are: -C ANS(3) double :: Result (finite, single pole, -C double pole) -C PREC_FOUND double :: Relative accuracy estimated for -C the result -C Returns -1 if no stab test could be performed. -C RET_CODE integer :: Return code. See below for details -C -C Return code conventions: RET_CODE = H*100 + T*10 + U -C -C H == 1 -C Stability unknown. -C H == 2 -C Stable PS (SPS) point. -C No stability rescue was necessary. -C H == 3 -C Unstable PS (UPS) point. -C Stability rescue necessary, and successful. -C H == 4 -C Exceptional PS (EPS) point. -C Stability rescue attempted, but unsuccessful. -C -C T == 1 -C Default computation (double prec.) was performed. -C T == 2 -C Quadruple precision was used for this PS point. -C T == 3 -C MadLoop in initialization phase. Only double precision used. -C T == 4 -C MadLoop in initialization phase. Quadruple precision used. -C -C U is a number left for future use (always set to 0 for now). -C example: TIR vs OPP usage. -C - IMPLICIT NONE -C -C CONSTANTS -C - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INCLUDE 'nsquaredSO.inc' -C -C ARGUMENTS -C - REAL*8 P(0:3,NEXTERNAL) - REAL*8 ANS(0:3,0:NSQUAREDSO) - REAL*8 PREC_ASKED,PREC_FOUND(0:NSQUAREDSO) - INTEGER RET_CODE -C -C GLOBAL VARIABLES -C - REAL*8 USER_STAB_PREC - COMMON/ML5_0_USER_STAB_PREC/USER_STAB_PREC - - INTEGER I - - INTEGER H,T,U - REAL*8 ACCURACY(0:NSQUAREDSO) - COMMON/ML5_0_ACC/ACCURACY,H,T,U - - LOGICAL BYPASS_CHECK, ALWAYS_TEST_STABILITY - COMMON/ML5_0_BYPASS_CHECK/BYPASS_CHECK, ALWAYS_TEST_STABILITY - -C ---------- -C BEGIN CODE -C ---------- - USER_STAB_PREC = PREC_ASKED - CALL ML5_0_SLOOPMATRIX(P,ANS) - IF(ALWAYS_TEST_STABILITY.AND.(H.EQ.1.OR.ACCURACY(0).LT.0.0D0)) - $ THEN - BYPASS_CHECK = .TRUE. - CALL ML5_0_SLOOPMATRIX(P,ANS) - BYPASS_CHECK = .FALSE. -C Make sure we correctly return an initialization-type T code - IF (T.EQ.2) T=4 - IF (T.EQ.1) T=3 - ENDIF - -C Reset it to default value not to affect next runs - USER_STAB_PREC = -1.0D0 - DO I=0,NSQUAREDSO - PREC_FOUND(I)=ACCURACY(I) - ENDDO - RET_CODE=100*H+10*T+U - - END - diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/loop_matrix.ps b/UNITTEST_proc/SubProcesses/P0_gg_ttx/loop_matrix.ps deleted file mode 100644 index 25a20ffd0611c7b8ea5e09d127993fe95ff481fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46706 zcmeHQ>2F-gasU4QisugtXn}~Fcg~Cf173U0Bu4D`$cZ2@M&yVjOmXDlXjg=w{O$Qw zRUg&e)#Q-TdbQ39yAnCCySnbH`}KVBli&UE5b)1qzZFAVs4cmD3p_V#eLyFJ|fwEc(e%{SY__4x*mez&>Y;-hxPxS#xH zbMg24&D*Qyi{^{=YzqeZ9HdZ{FOs7yHe(x9zL@)(@NhwE4|1fBxHl`ez>h zuXjM9J^R&v{`NOt{kHx34`2N|fPB@y-S22R&HH-u&Gkk5>y!46@7}!G?(f>ej)AJh zF5F@#?Thm-+itz?@$la;_Ih{Q_9sjK@xV*|atAmdsomUOw10WGy*pqSgT<`&>yuxf zxRrkX?$0Ni^OK8r`>V|xOl?ljZg+2Y*EF|Vv=`ggEk4>~g~|Q$_PQNTy0M$q{X7lR znm(p!`!~Cb_QS=yx9u=v;`KM}>zmzf&%eESchlazd-ajWo}S%ZU*5JK7VYJ>{m^}E zKfJ_W*RQuXcUu_&Xs6b&N^PtWe%T!xrF1v2kx6+kwg(p^XPVZ=KJ_tbB2Lu_yF8)&j8}=-u=uB1-1uX zr)$pm-@YZO;csHtt2>@X3(8ZH5aD_ujF!LmEZd&{7Tj*Z8Gg1Wb7O>Me%D?eTFl3Q zFa|#{ZlnVZ$p|n=`cMNNST4d)+nxpN29v5VnMB^39c*^jF4_*uINfcq4ABIb*O66@ z={MK6G~r|Wdbe*Nl--}V_ywRzjiIw|P5Icua^i8qa^k59i*zXp3(~lO{R3?fvt@jV zHNx7nEo-T8`2D$1OTwioTCz^pnU`8B_m~6j@KBzEl}S6W1hbNOPyg#V`@LJ|Tr}a` zTQMt!6Fw7dNzLnU1(j06h|V*hO$2QYaF#;I;fhqU$544B>Y5D$FBa_$tO}!{r&k^Q zLXHg5q~G{2axw(mX#_EF(Lmj3l8nGFVG@7TvoG?Knrkxri^G+gLeIoIIdlzUAu|z! zagZ>dOgA%@fCi1CIo(RUBK#+b>}&Gxe^Yfj}l0T{{#S`vxR4c zhrut*x5HI)zPnQ&h-W*-wm19z?%U>r_ZaNg5f>OM^5TdB__^6T2XTgHB54{aqrxW` zUmr_!FxG(RAlx6=Lg`Zv|Mm6FO>{hOuXcysZS&znG{bXDQ&YY7N^mjqqSmV5#Jf42H-m&!addJXz@l5)Eu<}Qo;GBizAX@3Q zQGLR8n`z2T^Fi`LN;nZi_d6Jqq?BYq2!3!F>?pjW6-#-drsS3)a7o3311HaM&F=jP z8koZUi0mg|E$$7Wn85*Sc+d)b_-?W|B9q(`PpDWqhg|Pbfx8R_?i#wO&o$`me@II7 zKPZq49tjFEsOZ)%Z{Cqt2-R+=(hd~@)@r0K>-?Irylaf|j(wPv8Af@>#gzBy zUY{js$edW-HBu7B@{U!&nuAEF>oV%qurB~9z993TVS1ywCtP-^VHymTcdiWPk^@Zh z&?@C!6UsZ%_lL?mf=iKw%RA~OV0^W_Yx0_qN)R?F&`0x#CxM4x1)dQbsp@rgC17(U zhhl59Kfgs-#y=lXDsmCz^^u@*3g8M=XxXJ;i6;`iJ(TdoRVk8~oO}1ej)Kr~w(sD& z@XQZ5`N_X?ecy83dbvkadAG+CZlHyQuC6aHxp7pn&&-4XN`PA@ihS2wr8aX0_vK9GO@8wCW2q+hbgBz@H)GI=IA z>Ol*Wk1FoDar1{se-K#kut8kmllCkvbr2iBV3F(Nq z4!ANj>!;cQ7urCPMKwab+De)%T~DvxwA^t4w<-In)qpF_co(K(?6mu-4V&9>0hju+ zX+M>sv>9+iAN!bq+i<`QwPc9)gj(4}Mg1#H#nyy3--Tb0SB8k0CbE*n^59O2^fNLghoByN6)7U)d;ntHa>vg7;@ z3zGUdD_}K1v7<-8Hh9FIHw7^-1d4{D0dJ+0PJnHSpaxrN#0kW7hS~XPy#U!i{Rh&R z6bT6Ufan!l{xRW>TO*tscYbT+yG*#Bvnx?oYPUP$w}{9=WJ*gpJ!u{p5f#dC7OpTq z=g+x(<2>GZ5lX^?nzO?QYR*ZIQ}ZnSry?_^|FTj&{U^s6(*F=RYUzJrFE}*7y9Ce8 zFCOtf60HtugFs@H{zOV?$%xRQ6Z2xWaTL{`NV)BbPXB-<#kHjV#DpqCDK_h&2~_1= z;DAsdx(yvc2+A$)$EAh5eIeUCEa}j9z(Dv%p7j2PU8{2&jHr8pi8MlI$JKw#%rwveUcXO5b);DT!ir}!p35O4o_?*An?{VmZPj58XV7a}! z*&Ij{(em?qS9s`_!kOwCoJq7%BOB=JPLp`zp z251Dp&+$+0u6EywOd@;vvmB~0Vm#BKIlB~HjUA!XiNbbBK~?xG*$2b1+0YrRCobOeZ^CJq9K)-OE4h=-k-r>)Q)9J0v5`>Gi=s{l~-R=K4H)e0SfT{_+0JtKCid zpgH|^dw~N~&FP2s^d6rwtr{7Q zNGR?tfb|>e4Bmg*=q-1CLLd02yiM=tp)VOe_n&ALn$w%@?Imm$6N9Mk!;b{r%c(hi|LzuAiIIMe zPn_@N0pgJZCJ!*9YlS8r@Nzs^h17-xj3_E3Rh}dEs`=&gUQd7G<5Y)$DUd<97jd=? zmPU#oQV`CChXq~JiJazO$A?0zIn4;m1^_@pSoWCaCzNH+8}ZwMvfwF3pLF0Pz_5yP zPX#{n6LChpnW%Tez_<^q6Ce^`MC7}5oR`9Q2{$X-@L)l=#DRVA zpbkf^uVLaye+p+MaJmzS*TAQrmM8sc7{|r5>iTi++i5+V^xbM2SL<%k&BM_4EFcln zncE2mj{UfzbMMQ3(XSVCKXfAy?v^LrV%;ytahevZ4mFEZTFr~Y{{%+1I4Pg3IzXJu zRkm!HIfjWElM?fJIiD<7-8glN)p|9|%QnGwQDQr-PFCy1vY)1LTz4y!fdSjFriJXh z?y{A_#34-7V$p~zP4Bx$)Wzv>I}M}OSQH`rss-Y9SPt(%kZNT^+ZVt8<<~zO|E~T0 zufG1-A`G5jT(CT787y(4pGoHxyQWTza6Kl9a|jSHja6&e&6sVFk2gwa3DzCGoFadm zWswPTGqqFZO|V*^sZiF4E*uL7&7g>BE}zB~#xQLDPGs>EqHETG8|lG=Xl8G=0xMPo(uq1G*J!@;Iz(8lWfk0&ty}OFxoo zwBxdBE^x9uVqGzpWC_M|fKVnK7yDlDgws%p8e@xKHjIl_fC&IaXb;MPHP^OOE(T zEThx%)qFB*7o_CkeL7;HMlMR9+(@y8B7b!Jg{~)SL>-0TSvx8$PLOxMAf`C=6mqynYei2Bcuh+G2PoUJ%q|F~y6)>2bb9$%~3A zJHT)l5LdE_B4iX^3`l*H&KA5Fg^3AB=jhX+6$?NrdNL<}kfD;lHy(&(DPeW+-^tu{+ad|JDS*QC zD4`6vvY>|BElvjg2RSmzCmXKwJ_OtHJ~jIK#VTE+L&i=aPU9f~z6T7g?olcdJ80=D zIIk^~`uFRUT}a?LA6J&5RHt=O1!aMzJo=UDng)+Wb_yBPDCBc{q*j_XwY~*~RilS- z&#T3{o99)BcZgRLBFB7!PgXt3p&ndWjKNH(E?f5}-EvrB#&TE>Ll1d&0J2`dXO4@x z>uT-hM zNvjv6fgIv-kyC6Txm0OTGN&vrk@-U+chR>Zb89)4x%D8I`3U>d{9Xc&s>lt1;yaB8 zg~1yuWxo0l!Z>k~yqW>GaMr^LveADY^3{%$6=yvn1JaPFi9#;9iiR?tQL^;hS4Wy8 zqhYEl%P44YV2N1fM_je5b*rx0pg;svBU!2HC{Sgz@-Ms z$ciVRt|9d>L;JPI*3$EPu79xN3 zq{)aGrJxG&kq9?W7??r~{G`&LL%Ri~!8{}xy$ayzT){@5f&;2F=$2~%RB2%NM4;B~ zTq^r_nLs+U;sDBsKh0^DXF28x;Q%6w4R0$EAT!d*U!~z~WC9a<;5rkCNmw)|ieB6l z1UGeTg%cO-lu8+Szywh!GgZpvqF1F`X!v+p&UjF43mDOPMunpAh#F|YW3F2d@|LKz zQ0kW=!Nf>1B?~Sus2N$N0n5kQt`#$_E>{Li>BTEFTpEDFq!KJ^FeE)7jFj$TPbAl% zc1G}o#|X)Pl#6c!Ez>SlbZ-`6ET0-u3Kf?H%vsl8t^PT*Ww zgDgMGXgD()>wWtw6v=N0DJ2@(jZDJHeB9PWQlCd>V9_S~EoEm)Xwy8Fjja*M1tb%E zQFPrtDM*`uu_#z8Z{U)GbZ8|hFkG1Eu<@WUG9&h6x*Z9i*u#zDGKd#&jUZmPT^GbF z##<$$bkVX=q=e#J^pI_5MVew$y#`IG+k{4HqHYgwLAeTaNc&bXDXOh#5L`GV7gUFQ zZz?z<3kdt0GKVBQy7i)4cB|zQX9%=~jnlg58I9C~UE@>)PFSo~wZg*46vq`xc)d`t zl4ygZWMt)4{FQW#K1bcFIVG#OHETIGed|H)w+$o8-FA?R?+m1-9lZduojCR>+XhBb z(4(Q82-a|L(mYa1PE}{#C8SP&P2!Iv1^rx;c{Bw0OKJjDu~Q=Nj7avW_aO{Ciq@T# z6y&|T$eAic>jC#8HOWR+kToQuKLaa2lO8*hVTAJz2er~I9SNKr_U&{MA8D!rk(_|& zRr=eHXm%uj(7(;Li&Tp4c68`SoQm4fA6XLOR&o_9g-a*9Rn#ufq^Ts%Ck09SPk965 zTvRgj_?$raUdEh49;0micSzDS(or7dqH9h4T)0LakP9OM_Iv8bclE2y=#nak#<8ztXvL6=mj8e^n0^2)|KU@% z{0$#0=MoJcTpUD~v;i>DWqM zVK`^$Xc`ZESMBBE1ZT+Nt33mb6J>=KbxTY_Kwhoy4t&Ji!h=&LpgHat^N*S$@1|?@=>n zG2?Y6w29Dy8<%Ko4@iWUYaH*x(bayyMoUzf#HC}GJVgPVhm9vV1XYW+WrP<&tE7n< zfN*{26)u)A!&PEv{eWIkhB{tKI_Vd9Jz>VI85{gdg?qHLzC@j}|8%KAcIrKVwZ5e>`ePUWvsL}hvSkiPE>R2zlHal&+L#q^DirnK+N>PZwp5$OBr zD8ST7j7Sm%yw78cKv1vJs%a`a1Jx}M1D-4d!od;wS%t^}#X*wmm9JE&w9~h!x$$i1 zxwSg?qOAuEM4@s-lR8FdlH>Q$g)iC!RWXi56JAamj_`F#HI-*X6Tk_mrs#@W6Ala% zu`P|#3bgMI2)03T(Yg9Ko*Jl%s$I9ck zX2jW*p;nxPrcVyj=lg%rztv#;6}tMCeB?!vB2y`MoFpO1H~*9yc=#oO&Nv=;j2kGn z3`SfF_ygE77{B8!gGamTdEsyLH?pJSQI?3opH+|D2w=WJnssrE_D0r?j#QSd0D8$n zw-#1bd!sm7ZM8S%McUrLMPuO(ljz?NCyMsQgk&PcAgTBt&%3{?xj5k<*lst z209u^djofg1=K@6Xkoqt&FM;EVoa2)qO6jna}jslMzx6!#r-~ZzkCXmHY-&QWSoXf z$5xV{GFXV14NqRa7eQS&YGT*kL8s`-I}YVW{om|s4BTu7;owYR$3}Z2zv(H4ale@% zPz*&kL_{rps@jXUMg)jbbR$cef50zMFxNGCl1$K!h3alZ&rHn?r|3myQi#oHZWLlu zF4vu7&Eytct8Z?k_8Dy%wQ2N%PkGP5@O-itVR$}ypd7W^_a_xiO3Z)?Jl|)sCGp74 zizdqGKxCT{s)h!I-$&=#kWQ6Cd7vqjEwK?V)g)qz`Y4?NBCNWQf@j_EK>HUJ;J!03 zCYkn&sO;4>jR$_?EL;d^ZT)BBizZzKC=4Lo)pQy=|M{+&^2OnLq{^{JAD`1Eq_Sz_ zU}8G<==dyLGJJet((a5~VbW1IC_vZtAM$-h0-u$?Im4nbeDEURA#}w{CaTyQ4+@nx zLRY2~QE)_HtuaqKjry(>qgC?2W|ZH2fL#Rw(Z`&&UcE*&$zoYFEaU{OSevUP$GK}sdzIW0TSG%yX}nL_A(C_ zJbd2}U~_xih7G+y%HLI6h;qE3()N__k7wz=v0iYpz1QiGsE(Z40R!)z| zXoMlj4B;O4Dkf)fG{V7C;LfQMU%Idn!(|A2=`FUv>*hWQ*a~MTKifDSkbA3rYz?nxy6DLa-v! z@U7KT-@+&EdKbR6=r$X^mC6h_iJ&yvK3wfn-6(nj|DN6;reI&$7x8{3_(&tz*Zt+g z`y#X~bF(bF%Vow!=c{X<>Nyk zMepQq`kwO2{o-_;3w`6C+zZ23dFDNk%c~G~MDK-h`nK~FigXW$wBc}h70Z+Is_!2! zDc`lYQav#Gv%aJpJ%fm-s6=)$zT$)QQDA+PTvU)QEnUb-aO70FF`;#byz+N`+T9(< zS0~>Uit-*!_LfPs5kl~LIP4w~tQ>WZ7?wxIe?04+THoh<)*Z+5qxC(hjm(vbRM}Dn zxO18u0O(#Y+4rGKpHu4#>mhzp?Jo6R(Fi~qg1R9u(PMGv>eEW^NCTChT?ZwgXJ41D z;tJ5?MlTa8vsIq%FAJ|;g7NS{WX&=gKX>vnzxhNVXcUM8T?~-CW+G)-afa5YZU@|6 z``qf54&iBa>Jm|0Ak~-CF2YlV80i67PxU$?S2a|uhoF=0*Px>h0_gRN@*i${YN#W< z*x*hOEBr^?4MZzcZ_3y6#BB)=kUQ#Y%SX-taxfRc1?j08WClhWO(Whh)UNCz=AaY0 zJLvwaFUlFP<$|+o@r!a$EZ{{3Ppiigj&h!iG+DWrHF(N zw^JFYAXxN;I*El@FDP0G(2I>^nXP#58_D$x8l>GzAcAz`CWyvKGgDaz-aaI6klzd( z5j3L7kBwgIwAAO^=rs-}9n*@E($Dok`9zHrkxGAPFA(~Z9~zDNL-CHAb6lepJw^A@ z^8*(6a1%~Y6vNTzY82(A=iCINvnLd}ZOJGWMo8&1nMmCT9f}nzlww*qr_t3YN-0=a zVZ^a41q~~dw{{B|8SgzGyWL{cSI6zPXjDqvAKYxAIF#h0baDD|yDbK~M{Txf5oyeo zD|W9wKd{;I@agEmI8=0u4HoU-xt%|8JJ@|m`ltQc%K1~agOQETIF-fUJ~s2;N-}Uv zbV)Ynqag^Y5YFGI#q+~cbr1qj>yYW?a9npl_8;aJkZFE+8iTJwwsZX{%25^K*!&^z ze9J-r5W(wN9p~~wdYV9YxWNEPL=NUv$itJV3XvQPA2Gre1N3%#z~)u-KplO_BQlEB zVjR!~#svi6IlhzyDeW5HJBb9n?|EMuvSQkmf9r6nm)siK4!7QkV~oeHZ^-B5#tUW?E1 z#nDdC*-eW9>n~UOb@ssQ)0@KVZ=Ugb5L^TGHmw_ z$q^`CE*o3P!v}8micot!v!1U}M5;_EE*HdtFuz2x;t(`g z%~EA2J$AMjMZDdrmWU`)xil2LAibW`@UT&`9< z3TRv(Ko^Q&vk3bsKbG<$W`Su0|1#)w01D zW(Y?zAPr382;F|z2px_UBh;+ZOK2SBg0yzdj41e!_0>DWS!gEes4*@Jm3lcW5wlQzEJ~Kcw>RsIwPJn}odq39rKnvF#Nzh^`79Jy zxmEOsQamz34M5T6vrzi(Hl=`yIG2T13|WJ9Kj+uJ_$+k7mtHHAjiy2x3yq+u!Id>&f2LYL!Jtk8j#o2EDqEj-2O z^3dE0V~$5Sk_l;G8b_Ch*3Ho2STRG*I=zH4!_noTxfw8GAsLD2k!ENl zcgI7DVAtN+0(c_HJK=vpb)bi1ID;4mWXx#=~CYsunvO#@7$YrAG*oqCRp73G6 KxxU%%oBsu__~W<$ diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/loop_num.f b/UNITTEST_proc/SubProcesses/P0_gg_ttx/loop_num.f deleted file mode 100644 index 83387cc67e..0000000000 --- a/UNITTEST_proc/SubProcesses/P0_gg_ttx/loop_num.f +++ /dev/null @@ -1,934 +0,0 @@ -C THE CORE SUBROUTINE CALLED BY CUTTOOLS WHICH CONTAINS THE HELAS -C CALLS BUILDING THE LOOP - - SUBROUTINE ML5_0_LOOPNUM(Q,RES) - USE ALOHA_OBJECT -C -C CONSTANTS -C - INTEGER NCOMB - PARAMETER (NCOMB=16) - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INTEGER NBORNAMPS - PARAMETER (NBORNAMPS=3) - INTEGER NLOOPAMPS - PARAMETER (NLOOPAMPS=129) - INTEGER NWAVEFUNCS - PARAMETER (NWAVEFUNCS=10) - INTEGER MAXLCOUPLINGS - PARAMETER (MAXLCOUPLINGS=4) - COMPLEX*16 IMAG1 - PARAMETER (IMAG1=(0D0,1D0)) -C -C ARGUMENTS -C - COMPLEX*16 Q(0:3) - COMPLEX*16 RES -C -C LOCAL VARIABLES -C - COMPLEX*16 CFTOT - COMPLEX*16 BUFF - INTEGER I,H -C -C GLOBAL VARIABLES -C - INTEGER WE(NEXTERNAL) - INTEGER ID, SYMFACT, MULTIPLIER, AMPLNUM - COMMON/ML5_0_LOOP/WE,ID,SYMFACT,MULTIPLIER,AMPLNUM - - LOGICAL GOODHEL(NCOMB) - LOGICAL GOODAMP(NLOOPAMPS,NCOMB) - COMMON/ML5_0_FILTERS/GOODAMP,GOODHEL - - INTEGER NTRY - LOGICAL CHECKPHASE,HELDOUBLECHECKED - REAL*8 REF - COMMON/ML5_0_INIT/NTRY,CHECKPHASE,HELDOUBLECHECKED,REF - - INTEGER CF_D(NLOOPAMPS,NBORNAMPS) - INTEGER CF_N(NLOOPAMPS,NBORNAMPS) - COMMON/ML5_0_CF/CF_D,CF_N - - COMPLEX*16 AMP(NBORNAMPS,NCOMB) - COMMON/ML5_0_AMPS/AMP - TYPE(ALOHA) W(NWAVEFUNCS,NCOMB) - COMMON/ML5_0_WFCTS/W - - INTEGER HELPICKED - COMMON/ML5_0_HELCHOICE/HELPICKED - - RES=(0.0D0,0.0D0) - - DO H=1,NCOMB - IF (((HELPICKED.EQ.-1).OR.(HELPICKED.EQ.H)) - $ .AND.((CHECKPHASE.OR..NOT.HELDOUBLECHECKED).OR.(GOODHEL(H) - $ .AND.GOODAMP(AMPLNUM,H)))) THEN - CALL ML5_0_LOOPNUMHEL(-Q,BUFF,H) - DO I=1,NBORNAMPS - CFTOT=DCMPLX(CF_N(AMPLNUM,I)/DBLE(ABS(CF_D(AMPLNUM,I))) - $ ,0.0D0) - IF(CF_D(AMPLNUM,I).LT.0) CFTOT=CFTOT*IMAG1 - RES=RES+CFTOT*BUFF*DCONJG(AMP(I,H)) - ENDDO - ENDIF - ENDDO - RES=(RES*MULTIPLIER)/SYMFACT - - END - - SUBROUTINE ML5_0_LOOPNUMHEL(Q,RES,H) - USE ALOHA_OBJECT -C -C CONSTANTS -C - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INTEGER MAXLCOUPLINGS - PARAMETER (MAXLCOUPLINGS=4) - INTEGER NMAXLOOPWFS - PARAMETER (NMAXLOOPWFS=(NEXTERNAL+2)) - REAL*8 ZERO - PARAMETER (ZERO=0.D0) - INTEGER NWAVEFUNCS - PARAMETER (NWAVEFUNCS=10) - INTEGER NBORNAMPS - PARAMETER (NBORNAMPS=3) - INTEGER NLOOPAMPS - PARAMETER (NLOOPAMPS=129) - INTEGER NCOMB - PARAMETER (NCOMB=16) -C -C ARGUMENTS -C - COMPLEX*16 Q(0:3) - COMPLEX*16 RES - INTEGER H -C -C LOCAL VARIABLES -C - COMPLEX*16 BUFF(4) - TYPE(ALOHA) WL(NMAXLOOPWFS) - INTEGER I -C -C GLOBAL VARIABLES -C - COMPLEX*16 LC(MAXLCOUPLINGS) - COMPLEX*16 ML(NEXTERNAL+2) - COMMON/ML5_0_DP_LOOP/LC,ML - - INTEGER WE(NEXTERNAL) - INTEGER ID, SYMFACT,MULTIPLIER,AMPLNUM - COMMON/ML5_0_LOOP/WE,ID,SYMFACT,MULTIPLIER,AMPLNUM - - COMPLEX*16 AMP(NBORNAMPS,NCOMB) - COMMON/ML5_0_AMPS/AMP - TYPE(ALOHA) W(NWAVEFUNCS,NCOMB) - COMMON/ML5_0_WFCTS/W - -C ---------- -C BEGIN CODE -C ---------- - RES=(0.D0,0.D0) - IF (ID.EQ.1) THEN -C Loop diagram number 4 (might be others, just an example) - DO I=1,4 - CALL LCUT_V(Q(0),I,WL(2)) - CALL VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL VVV1LP0_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) - BUFF(I)=WL(4)%W(I) - ENDDO - CALL CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.2) THEN -C Loop diagram number 5 (might be others, just an example) - DO I=1,4 - CALL LCUT_V(Q(0),I,WL(2)) - CALL FFV1L_1(W(WE(1),H),WL(2),LC(1),ML(3),ZERO,WL(3)) - CALL FFV1LP0_3(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) - CALL VVV1LP0_1(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) - BUFF(I)=WL(5)%W(I) - ENDDO - CALL CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.3) THEN -C Loop diagram number 6 (might be others, just an example) - DO I=1,4 - CALL LCUT_AF(Q(0),I,WL(2)) - CALL FFV1LP0_3(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL FFV1L_2(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) - CALL FFV1L_2(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) - BUFF(I)=WL(5)%W(I) - ENDDO - CALL CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.4) THEN -C Loop diagram number 7 (might be others, just an example) - DO I=1,4 - CALL LCUT_AF(Q(0),I,WL(2)) - CALL FFV1LP0_3(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL FFV1L_2(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) - BUFF(I)=WL(4)%W(I) - ENDDO - CALL CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.5) THEN -C Loop diagram number 8 (might be others, just an example) - DO I=1,4 - CALL LCUT_V(Q(0),I,WL(2)) - CALL VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL FFV1L_2(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) - CALL FFV1LP0_3(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) - BUFF(I)=WL(5)%W(I) - ENDDO - CALL CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.6) THEN -C Loop diagram number 9 (might be others, just an example) - DO I=1,4 - CALL LCUT_F(Q(0),I,WL(2)) - CALL FFV1L_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL FFV1LP0_3(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) - CALL FFV1L_1(W(WE(3),H),WL(4),LC(3),ML(5),ZERO,WL(5)) - BUFF(I)=WL(5)%W(I) - ENDDO - CALL CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.7) THEN -C Loop diagram number 11 (might be others, just an example) - DO I=1,4 - CALL LCUT_V(Q(0),I,WL(2)) - CALL VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL FFV1L_1(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) - CALL FFV1LP0_3(W(WE(3),H),WL(4),LC(3),ML(5),ZERO,WL(5)) - BUFF(I)=WL(5)%W(I) - ENDDO - CALL CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.8) THEN -C Loop diagram number 12 (might be others, just an example) - DO I=1,4 - CALL LCUT_AF(Q(0),I,WL(2)) - CALL FFV1L_2(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL FFV1LP0_3(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) - CALL FFV1L_2(W(WE(3),H),WL(4),LC(3),ML(5),ZERO,WL(5)) - BUFF(I)=WL(5)%W(I) - ENDDO - CALL CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.9) THEN -C Loop diagram number 15 (might be others, just an example) - DO I=1,4 - CALL LCUT_V(Q(0),I,WL(2)) - CALL VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL VVV1LP0_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) - CALL FFV1L_2(W(WE(3),H),WL(4),LC(3),ML(5),ZERO,WL(5)) - CALL FFV1LP0_3(WL(5),W(WE(4),H),LC(4),ML(6),ZERO,WL(6)) - BUFF(I)=WL(6)%W(I) - ENDDO - CALL CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.10) THEN -C Loop diagram number 16 (might be others, just an example) - DO I=1,4 - CALL LCUT_V(Q(0),I,WL(2)) - CALL VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL VVV1LP0_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) - CALL FFV1L_1(W(WE(3),H),WL(4),LC(3),ML(5),ZERO,WL(5)) - CALL FFV1LP0_3(W(WE(4),H),WL(5),LC(4),ML(6),ZERO,WL(6)) - BUFF(I)=WL(6)%W(I) - ENDDO - CALL CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.11) THEN -C Loop diagram number 17 (might be others, just an example) - DO I=1,4 - CALL LCUT_V(Q(0),I,WL(2)) - CALL VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL VVV1LP0_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) - CALL VVV1LP0_1(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) - BUFF(I)=WL(5)%W(I) - ENDDO - CALL CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.12) THEN -C Loop diagram number 18 (might be others, just an example) - DO I=1,4 - CALL LCUT_V(Q(0),I,WL(2)) - CALL VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL VVVV1LP0_1(WL(3),W(WE(2),H),W(WE(3),H),LC(2),ML(4),ZERO - $ ,WL(4)) - BUFF(I)=WL(4)%W(I) - ENDDO - CALL CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.13) THEN -C Loop diagram number 18 (might be others, just an example) - DO I=1,4 - CALL LCUT_V(Q(0),I,WL(2)) - CALL VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL VVVV3LP0_1(WL(3),W(WE(2),H),W(WE(3),H),LC(2),ML(4),ZERO - $ ,WL(4)) - BUFF(I)=WL(4)%W(I) - ENDDO - CALL CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.14) THEN -C Loop diagram number 18 (might be others, just an example) - DO I=1,4 - CALL LCUT_V(Q(0),I,WL(2)) - CALL VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL VVVV4LP0_1(WL(3),W(WE(2),H),W(WE(3),H),LC(2),ML(4),ZERO - $ ,WL(4)) - BUFF(I)=WL(4)%W(I) - ENDDO - CALL CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.15) THEN -C Loop diagram number 19 (might be others, just an example) - DO I=1,4 - CALL LCUT_V(Q(0),I,WL(2)) - CALL VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL FFV1L_1(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) - CALL FFV1L_1(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) - CALL FFV1LP0_3(W(WE(4),H),WL(5),LC(4),ML(6),ZERO,WL(6)) - BUFF(I)=WL(6)%W(I) - ENDDO - CALL CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.16) THEN -C Loop diagram number 23 (might be others, just an example) - DO I=1,4 - CALL LCUT_AF(Q(0),I,WL(2)) - CALL FFV1L_2(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL FFV1LP0_3(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) - CALL VVV1LP0_1(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) - CALL FFV1L_2(W(WE(4),H),WL(5),LC(4),ML(6),ZERO,WL(6)) - BUFF(I)=WL(6)%W(I) - ENDDO - CALL CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.17) THEN -C Loop diagram number 24 (might be others, just an example) - DO I=1,4 - CALL LCUT_F(Q(0),I,WL(2)) - CALL FFV1L_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL FFV1L_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) - CALL FFV1LP0_3(W(WE(3),H),WL(4),LC(3),ML(5),ZERO,WL(5)) - CALL FFV1L_1(W(WE(4),H),WL(5),LC(4),ML(6),ZERO,WL(6)) - BUFF(I)=WL(6)%W(I) - ENDDO - CALL CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.18) THEN -C Loop diagram number 25 (might be others, just an example) - DO I=1,4 - CALL LCUT_AF(Q(0),I,WL(2)) - CALL FFV1L_2(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL FFV1L_2(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) - CALL FFV1LP0_3(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) - CALL FFV1L_2(W(WE(4),H),WL(5),LC(4),ML(6),ZERO,WL(6)) - BUFF(I)=WL(6)%W(I) - ENDDO - CALL CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.19) THEN -C Loop diagram number 26 (might be others, just an example) - DO I=1,4 - CALL LCUT_V(Q(0),I,WL(2)) - CALL VVVV1LP0_1(WL(2),W(WE(1),H),W(WE(2),H),LC(1),ML(3),ZERO - $ ,WL(3)) - CALL VVV1LP0_1(WL(3),W(WE(3),H),LC(2),ML(4),ZERO,WL(4)) - BUFF(I)=WL(4)%W(I) - ENDDO - CALL CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.20) THEN -C Loop diagram number 26 (might be others, just an example) - DO I=1,4 - CALL LCUT_V(Q(0),I,WL(2)) - CALL VVVV3LP0_1(WL(2),W(WE(1),H),W(WE(2),H),LC(1),ML(3),ZERO - $ ,WL(3)) - CALL VVV1LP0_1(WL(3),W(WE(3),H),LC(2),ML(4),ZERO,WL(4)) - BUFF(I)=WL(4)%W(I) - ENDDO - CALL CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.21) THEN -C Loop diagram number 26 (might be others, just an example) - DO I=1,4 - CALL LCUT_V(Q(0),I,WL(2)) - CALL VVVV4LP0_1(WL(2),W(WE(1),H),W(WE(2),H),LC(1),ML(3),ZERO - $ ,WL(3)) - CALL VVV1LP0_1(WL(3),W(WE(3),H),LC(2),ML(4),ZERO,WL(4)) - BUFF(I)=WL(4)%W(I) - ENDDO - CALL CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.22) THEN -C Loop diagram number 27 (might be others, just an example) - DO I=1,4 - CALL LCUT_V(Q(0),I,WL(2)) - CALL FFV1L_1(W(WE(1),H),WL(2),LC(1),ML(3),ZERO,WL(3)) - CALL FFV1LP0_3(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) - CALL VVVV1LP0_1(WL(4),W(WE(3),H),W(WE(4),H),LC(3),ML(5),ZERO - $ ,WL(5)) - BUFF(I)=WL(5)%W(I) - ENDDO - CALL CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.23) THEN -C Loop diagram number 27 (might be others, just an example) - DO I=1,4 - CALL LCUT_V(Q(0),I,WL(2)) - CALL FFV1L_1(W(WE(1),H),WL(2),LC(1),ML(3),ZERO,WL(3)) - CALL FFV1LP0_3(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) - CALL VVVV3LP0_1(WL(4),W(WE(3),H),W(WE(4),H),LC(3),ML(5),ZERO - $ ,WL(5)) - BUFF(I)=WL(5)%W(I) - ENDDO - CALL CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.24) THEN -C Loop diagram number 27 (might be others, just an example) - DO I=1,4 - CALL LCUT_V(Q(0),I,WL(2)) - CALL FFV1L_1(W(WE(1),H),WL(2),LC(1),ML(3),ZERO,WL(3)) - CALL FFV1LP0_3(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) - CALL VVVV4LP0_1(WL(4),W(WE(3),H),W(WE(4),H),LC(3),ML(5),ZERO - $ ,WL(5)) - BUFF(I)=WL(5)%W(I) - ENDDO - CALL CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.25) THEN -C Loop diagram number 28 (might be others, just an example) - DO I=1,1 - CALL LCUT_S(Q(0),I,WL(2)) - CALL GHGHGL_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL GHGHGL_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) - BUFF(I)=WL(4)%W(I) - ENDDO - CALL CLOSE_1(BUFF(1),RES) - ELSEIF (ID.EQ.26) THEN -C Loop diagram number 29 (might be others, just an example) - DO I=1,1 - CALL LCUT_AS(Q(0),I,WL(2)) - CALL GHGHGL_2(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL GHGHGL_2(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) - CALL GHGHGL_2(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) - BUFF(I)=WL(5)%W(I) - ENDDO - CALL CLOSE_1(BUFF(1),RES) - ELSEIF (ID.EQ.27) THEN -C Loop diagram number 30 (might be others, just an example) - DO I=1,1 - CALL LCUT_S(Q(0),I,WL(2)) - CALL GHGHGL_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL GHGHGL_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) - CALL GHGHGL_1(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) - BUFF(I)=WL(5)%W(I) - ENDDO - CALL CLOSE_1(BUFF(1),RES) - ELSEIF (ID.EQ.28) THEN -C Loop diagram number 31 (might be others, just an example) - DO I=1,4 - CALL LCUT_F(Q(0),I,WL(2)) - CALL FFV1L_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL FFV1L_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) - BUFF(I)=WL(4)%W(I) - ENDDO - CALL CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.29) THEN -C Loop diagram number 32 (might be others, just an example) - DO I=1,4 - CALL LCUT_AF(Q(0),I,WL(2)) - CALL FFV1L_2(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL FFV1L_2(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) - CALL FFV1L_2(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) - BUFF(I)=WL(5)%W(I) - ENDDO - CALL CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.30) THEN -C Loop diagram number 33 (might be others, just an example) - DO I=1,4 - CALL LCUT_F(Q(0),I,WL(2)) - CALL FFV1L_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL FFV1L_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) - CALL FFV1L_1(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) - BUFF(I)=WL(5)%W(I) - ENDDO - CALL CLOSE_4(BUFF(1),RES) - ENDIF - END - - SUBROUTINE ML5_0_MPLOOPNUM(Q,RES) - USE ALOHA_OBJECT - INCLUDE 'cts_mprec.h' - IMPLICIT NONE -C -C CONSTANTS -C - INTEGER NCOMB - PARAMETER (NCOMB=16) - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INTEGER NBORNAMPS - PARAMETER (NBORNAMPS=3) - INTEGER NLOOPAMPS - PARAMETER (NLOOPAMPS=129) - INTEGER NWAVEFUNCS - PARAMETER (NWAVEFUNCS=10) - INTEGER MAXLCOUPLINGS - PARAMETER (MAXLCOUPLINGS=4) - COMPLEX*32 IMAG1 - PARAMETER (IMAG1=(0E0_16,1E0_16)) -C -C ARGUMENTS -C - INCLUDE 'cts_mpc.h' - $ , INTENT(IN), DIMENSION(0:3) :: Q - INCLUDE 'cts_mpc.h' - $ , INTENT(OUT) :: RES -C -C LOCAL VARIABLES -C - COMPLEX*32 QPRES - COMPLEX*32 QPQ(0:3) - REAL*16 QPP(0:3,NEXTERNAL) - INTEGER I,J,H - COMPLEX*32 CFTOT - COMPLEX*32 BUFF -C -C GLOBAL VARIABLES -C - LOGICAL MP_DONE - COMMON/ML5_0_MP_DONE/MP_DONE - - REAL*16 MP_PS(0:3,NEXTERNAL),MP_P(0:3,NEXTERNAL) - COMMON/ML5_0_MP_PSPOINT/MP_PS,MP_P - - REAL*8 LSCALE - INTEGER CTMODE - COMMON/ML5_0_CT/LSCALE,CTMODE - - INTEGER WE(NEXTERNAL) - INTEGER ID, SYMFACT,MULTIPLIER,AMPLNUM - COMMON/ML5_0_LOOP/WE,ID,SYMFACT,MULTIPLIER,AMPLNUM - - LOGICAL GOODHEL(NCOMB) - LOGICAL GOODAMP(NLOOPAMPS,NCOMB) - COMMON/ML5_0_FILTERS/GOODAMP,GOODHEL - - INTEGER NTRY - LOGICAL CHECKPHASE,HELDOUBLECHECKED - REAL*8 REF - COMMON/ML5_0_INIT/NTRY,CHECKPHASE,HELDOUBLECHECKED,REF - - INTEGER CF_D(NLOOPAMPS,NBORNAMPS) - INTEGER CF_N(NLOOPAMPS,NBORNAMPS) - COMMON/ML5_0_CF/CF_D,CF_N - - COMPLEX*32 AMP(NBORNAMPS,NCOMB) - COMMON/ML5_0_MP_AMPS/AMP - TYPE(MP_ALOHA) W(NWAVEFUNCS,NCOMB) - COMMON/ML5_0_MP_WFS/W - - INTEGER HELPICKED - COMMON/ML5_0_HELCHOICE/HELPICKED -C ---------- -C BEGIN CODE -C ---------- - DO I=0,3 - QPQ(I) = Q(I) - ENDDO - QPRES=(0.0E0_16,0.0E0_16) - - IF(.NOT.MP_DONE.AND.CTMODE.EQ.0) THEN -C This is just to compute the wfs in quad prec - CALL ML5_0_MP_BORN_AMPS_AND_WFS(MP_P) - MP_DONE=.TRUE. - ENDIF - - DO H=1,NCOMB - IF (((HELPICKED.EQ.-1).OR.(HELPICKED.EQ.H)) - $ .AND.((CHECKPHASE.OR..NOT.HELDOUBLECHECKED).OR.(GOODHEL(H) - $ .AND.GOODAMP(AMPLNUM,H)))) THEN - CALL ML5_0_MPLOOPNUMHEL(-QPQ,BUFF,H) - DO I=1,NBORNAMPS - CFTOT=CMPLX(CF_N(AMPLNUM,I)/(1.0E0_16*ABS(CF_D(AMPLNUM,I))) - $ ,0.0E0_16,KIND=16) - IF(CF_D(AMPLNUM,I).LT.0) CFTOT=CFTOT*IMAG1 - QPRES=QPRES+CFTOT*BUFF*CONJG(AMP(I,H)) - ENDDO - ENDIF - ENDDO - QPRES=(QPRES*MULTIPLIER)/SYMFACT - - RES=QPRES - END - - SUBROUTINE ML5_0_MPLOOPNUMHEL(Q,RES,H) - USE ALOHA_OBJECT -C -C CONSTANTS -C - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INTEGER MAXLCOUPLINGS - PARAMETER (MAXLCOUPLINGS=4) - INTEGER NMAXLOOPWFS - PARAMETER (NMAXLOOPWFS=(NEXTERNAL+2)) - REAL*16 ZERO - PARAMETER (ZERO=0E0_16) - INTEGER NWAVEFUNCS - PARAMETER (NWAVEFUNCS=10) - INTEGER NBORNAMPS - PARAMETER (NBORNAMPS=3) - INTEGER NLOOPAMPS - PARAMETER (NLOOPAMPS=129) - INTEGER NCOMB - PARAMETER (NCOMB=16) -C -C ARGUMENTS -C - COMPLEX*32 Q(0:3) - COMPLEX*32 RES - INTEGER H -C -C LOCAL VARIABLES -C - COMPLEX*32 BUFF(4) - TYPE(MP_ALOHA) WL(NMAXLOOPWFS) - INTEGER I -C -C GLOBAL VARIABLES -C - COMPLEX*32 LC(MAXLCOUPLINGS) - COMPLEX*32 ML(NEXTERNAL+2) - COMMON/ML5_0_MP_LOOP/LC,ML - - INTEGER WE(NEXTERNAL) - INTEGER ID, SYMFACT,MULTIPLIER,AMPLNUM - COMMON/ML5_0_LOOP/WE,ID,SYMFACT,MULTIPLIER,AMPLNUM - - COMPLEX*32 AMP(NBORNAMPS,NCOMB) - COMMON/ML5_0_MP_AMPS/AMP - TYPE(MP_ALOHA) W(NWAVEFUNCS,NCOMB) - COMMON/ML5_0_MP_WFS/W -C ---------- -C BEGIN CODE -C ---------- - RES=(0E0_16,0E0_16) - IF (ID.EQ.1) THEN -C Loop diagram number 4 (might be others, just an example) - DO I=1,4 - CALL MP_LCUT_V(Q(0),I,WL(2)) - CALL MP_VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL MP_VVV1LP0_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) - BUFF(I)=WL(4)%W(I) - ENDDO - CALL MP_CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.2) THEN -C Loop diagram number 5 (might be others, just an example) - DO I=1,4 - CALL MP_LCUT_V(Q(0),I,WL(2)) - CALL MP_FFV1L_1(W(WE(1),H),WL(2),LC(1),ML(3),ZERO,WL(3)) - CALL MP_FFV1LP0_3(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) - CALL MP_VVV1LP0_1(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) - BUFF(I)=WL(5)%W(I) - ENDDO - CALL MP_CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.3) THEN -C Loop diagram number 6 (might be others, just an example) - DO I=1,4 - CALL MP_LCUT_AF(Q(0),I,WL(2)) - CALL MP_FFV1LP0_3(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL MP_FFV1L_2(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) - CALL MP_FFV1L_2(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) - BUFF(I)=WL(5)%W(I) - ENDDO - CALL MP_CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.4) THEN -C Loop diagram number 7 (might be others, just an example) - DO I=1,4 - CALL MP_LCUT_AF(Q(0),I,WL(2)) - CALL MP_FFV1LP0_3(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL MP_FFV1L_2(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) - BUFF(I)=WL(4)%W(I) - ENDDO - CALL MP_CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.5) THEN -C Loop diagram number 8 (might be others, just an example) - DO I=1,4 - CALL MP_LCUT_V(Q(0),I,WL(2)) - CALL MP_VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL MP_FFV1L_2(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) - CALL MP_FFV1LP0_3(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) - BUFF(I)=WL(5)%W(I) - ENDDO - CALL MP_CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.6) THEN -C Loop diagram number 9 (might be others, just an example) - DO I=1,4 - CALL MP_LCUT_F(Q(0),I,WL(2)) - CALL MP_FFV1L_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL MP_FFV1LP0_3(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) - CALL MP_FFV1L_1(W(WE(3),H),WL(4),LC(3),ML(5),ZERO,WL(5)) - BUFF(I)=WL(5)%W(I) - ENDDO - CALL MP_CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.7) THEN -C Loop diagram number 11 (might be others, just an example) - DO I=1,4 - CALL MP_LCUT_V(Q(0),I,WL(2)) - CALL MP_VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL MP_FFV1L_1(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) - CALL MP_FFV1LP0_3(W(WE(3),H),WL(4),LC(3),ML(5),ZERO,WL(5)) - BUFF(I)=WL(5)%W(I) - ENDDO - CALL MP_CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.8) THEN -C Loop diagram number 12 (might be others, just an example) - DO I=1,4 - CALL MP_LCUT_AF(Q(0),I,WL(2)) - CALL MP_FFV1L_2(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL MP_FFV1LP0_3(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) - CALL MP_FFV1L_2(W(WE(3),H),WL(4),LC(3),ML(5),ZERO,WL(5)) - BUFF(I)=WL(5)%W(I) - ENDDO - CALL MP_CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.9) THEN -C Loop diagram number 15 (might be others, just an example) - DO I=1,4 - CALL MP_LCUT_V(Q(0),I,WL(2)) - CALL MP_VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL MP_VVV1LP0_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) - CALL MP_FFV1L_2(W(WE(3),H),WL(4),LC(3),ML(5),ZERO,WL(5)) - CALL MP_FFV1LP0_3(WL(5),W(WE(4),H),LC(4),ML(6),ZERO,WL(6)) - BUFF(I)=WL(6)%W(I) - ENDDO - CALL MP_CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.10) THEN -C Loop diagram number 16 (might be others, just an example) - DO I=1,4 - CALL MP_LCUT_V(Q(0),I,WL(2)) - CALL MP_VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL MP_VVV1LP0_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) - CALL MP_FFV1L_1(W(WE(3),H),WL(4),LC(3),ML(5),ZERO,WL(5)) - CALL MP_FFV1LP0_3(W(WE(4),H),WL(5),LC(4),ML(6),ZERO,WL(6)) - BUFF(I)=WL(6)%W(I) - ENDDO - CALL MP_CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.11) THEN -C Loop diagram number 17 (might be others, just an example) - DO I=1,4 - CALL MP_LCUT_V(Q(0),I,WL(2)) - CALL MP_VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL MP_VVV1LP0_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) - CALL MP_VVV1LP0_1(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) - BUFF(I)=WL(5)%W(I) - ENDDO - CALL MP_CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.12) THEN -C Loop diagram number 18 (might be others, just an example) - DO I=1,4 - CALL MP_LCUT_V(Q(0),I,WL(2)) - CALL MP_VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL MP_VVVV1LP0_1(WL(3),W(WE(2),H),W(WE(3),H),LC(2),ML(4) - $ ,ZERO,WL(4)) - BUFF(I)=WL(4)%W(I) - ENDDO - CALL MP_CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.13) THEN -C Loop diagram number 18 (might be others, just an example) - DO I=1,4 - CALL MP_LCUT_V(Q(0),I,WL(2)) - CALL MP_VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL MP_VVVV3LP0_1(WL(3),W(WE(2),H),W(WE(3),H),LC(2),ML(4) - $ ,ZERO,WL(4)) - BUFF(I)=WL(4)%W(I) - ENDDO - CALL MP_CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.14) THEN -C Loop diagram number 18 (might be others, just an example) - DO I=1,4 - CALL MP_LCUT_V(Q(0),I,WL(2)) - CALL MP_VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL MP_VVVV4LP0_1(WL(3),W(WE(2),H),W(WE(3),H),LC(2),ML(4) - $ ,ZERO,WL(4)) - BUFF(I)=WL(4)%W(I) - ENDDO - CALL MP_CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.15) THEN -C Loop diagram number 19 (might be others, just an example) - DO I=1,4 - CALL MP_LCUT_V(Q(0),I,WL(2)) - CALL MP_VVV1LP0_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL MP_FFV1L_1(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) - CALL MP_FFV1L_1(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) - CALL MP_FFV1LP0_3(W(WE(4),H),WL(5),LC(4),ML(6),ZERO,WL(6)) - BUFF(I)=WL(6)%W(I) - ENDDO - CALL MP_CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.16) THEN -C Loop diagram number 23 (might be others, just an example) - DO I=1,4 - CALL MP_LCUT_AF(Q(0),I,WL(2)) - CALL MP_FFV1L_2(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL MP_FFV1LP0_3(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) - CALL MP_VVV1LP0_1(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) - CALL MP_FFV1L_2(W(WE(4),H),WL(5),LC(4),ML(6),ZERO,WL(6)) - BUFF(I)=WL(6)%W(I) - ENDDO - CALL MP_CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.17) THEN -C Loop diagram number 24 (might be others, just an example) - DO I=1,4 - CALL MP_LCUT_F(Q(0),I,WL(2)) - CALL MP_FFV1L_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL MP_FFV1L_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) - CALL MP_FFV1LP0_3(W(WE(3),H),WL(4),LC(3),ML(5),ZERO,WL(5)) - CALL MP_FFV1L_1(W(WE(4),H),WL(5),LC(4),ML(6),ZERO,WL(6)) - BUFF(I)=WL(6)%W(I) - ENDDO - CALL MP_CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.18) THEN -C Loop diagram number 25 (might be others, just an example) - DO I=1,4 - CALL MP_LCUT_AF(Q(0),I,WL(2)) - CALL MP_FFV1L_2(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL MP_FFV1L_2(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) - CALL MP_FFV1LP0_3(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) - CALL MP_FFV1L_2(W(WE(4),H),WL(5),LC(4),ML(6),ZERO,WL(6)) - BUFF(I)=WL(6)%W(I) - ENDDO - CALL MP_CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.19) THEN -C Loop diagram number 26 (might be others, just an example) - DO I=1,4 - CALL MP_LCUT_V(Q(0),I,WL(2)) - CALL MP_VVVV1LP0_1(WL(2),W(WE(1),H),W(WE(2),H),LC(1),ML(3) - $ ,ZERO,WL(3)) - CALL MP_VVV1LP0_1(WL(3),W(WE(3),H),LC(2),ML(4),ZERO,WL(4)) - BUFF(I)=WL(4)%W(I) - ENDDO - CALL MP_CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.20) THEN -C Loop diagram number 26 (might be others, just an example) - DO I=1,4 - CALL MP_LCUT_V(Q(0),I,WL(2)) - CALL MP_VVVV3LP0_1(WL(2),W(WE(1),H),W(WE(2),H),LC(1),ML(3) - $ ,ZERO,WL(3)) - CALL MP_VVV1LP0_1(WL(3),W(WE(3),H),LC(2),ML(4),ZERO,WL(4)) - BUFF(I)=WL(4)%W(I) - ENDDO - CALL MP_CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.21) THEN -C Loop diagram number 26 (might be others, just an example) - DO I=1,4 - CALL MP_LCUT_V(Q(0),I,WL(2)) - CALL MP_VVVV4LP0_1(WL(2),W(WE(1),H),W(WE(2),H),LC(1),ML(3) - $ ,ZERO,WL(3)) - CALL MP_VVV1LP0_1(WL(3),W(WE(3),H),LC(2),ML(4),ZERO,WL(4)) - BUFF(I)=WL(4)%W(I) - ENDDO - CALL MP_CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.22) THEN -C Loop diagram number 27 (might be others, just an example) - DO I=1,4 - CALL MP_LCUT_V(Q(0),I,WL(2)) - CALL MP_FFV1L_1(W(WE(1),H),WL(2),LC(1),ML(3),ZERO,WL(3)) - CALL MP_FFV1LP0_3(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) - CALL MP_VVVV1LP0_1(WL(4),W(WE(3),H),W(WE(4),H),LC(3),ML(5) - $ ,ZERO,WL(5)) - BUFF(I)=WL(5)%W(I) - ENDDO - CALL MP_CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.23) THEN -C Loop diagram number 27 (might be others, just an example) - DO I=1,4 - CALL MP_LCUT_V(Q(0),I,WL(2)) - CALL MP_FFV1L_1(W(WE(1),H),WL(2),LC(1),ML(3),ZERO,WL(3)) - CALL MP_FFV1LP0_3(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) - CALL MP_VVVV3LP0_1(WL(4),W(WE(3),H),W(WE(4),H),LC(3),ML(5) - $ ,ZERO,WL(5)) - BUFF(I)=WL(5)%W(I) - ENDDO - CALL MP_CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.24) THEN -C Loop diagram number 27 (might be others, just an example) - DO I=1,4 - CALL MP_LCUT_V(Q(0),I,WL(2)) - CALL MP_FFV1L_1(W(WE(1),H),WL(2),LC(1),ML(3),ZERO,WL(3)) - CALL MP_FFV1LP0_3(W(WE(2),H),WL(3),LC(2),ML(4),ZERO,WL(4)) - CALL MP_VVVV4LP0_1(WL(4),W(WE(3),H),W(WE(4),H),LC(3),ML(5) - $ ,ZERO,WL(5)) - BUFF(I)=WL(5)%W(I) - ENDDO - CALL MP_CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.25) THEN -C Loop diagram number 28 (might be others, just an example) - DO I=1,1 - CALL MP_LCUT_S(Q(0),I,WL(2)) - CALL MP_GHGHGL_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL MP_GHGHGL_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) - BUFF(I)=WL(4)%W(I) - ENDDO - CALL MP_CLOSE_1(BUFF(1),RES) - ELSEIF (ID.EQ.26) THEN -C Loop diagram number 29 (might be others, just an example) - DO I=1,1 - CALL MP_LCUT_AS(Q(0),I,WL(2)) - CALL MP_GHGHGL_2(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL MP_GHGHGL_2(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) - CALL MP_GHGHGL_2(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) - BUFF(I)=WL(5)%W(I) - ENDDO - CALL MP_CLOSE_1(BUFF(1),RES) - ELSEIF (ID.EQ.27) THEN -C Loop diagram number 30 (might be others, just an example) - DO I=1,1 - CALL MP_LCUT_S(Q(0),I,WL(2)) - CALL MP_GHGHGL_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL MP_GHGHGL_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) - CALL MP_GHGHGL_1(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) - BUFF(I)=WL(5)%W(I) - ENDDO - CALL MP_CLOSE_1(BUFF(1),RES) - ELSEIF (ID.EQ.28) THEN -C Loop diagram number 31 (might be others, just an example) - DO I=1,4 - CALL MP_LCUT_F(Q(0),I,WL(2)) - CALL MP_FFV1L_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL MP_FFV1L_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) - BUFF(I)=WL(4)%W(I) - ENDDO - CALL MP_CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.29) THEN -C Loop diagram number 32 (might be others, just an example) - DO I=1,4 - CALL MP_LCUT_AF(Q(0),I,WL(2)) - CALL MP_FFV1L_2(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL MP_FFV1L_2(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) - CALL MP_FFV1L_2(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) - BUFF(I)=WL(5)%W(I) - ENDDO - CALL MP_CLOSE_4(BUFF(1),RES) - ELSEIF (ID.EQ.30) THEN -C Loop diagram number 33 (might be others, just an example) - DO I=1,4 - CALL MP_LCUT_F(Q(0),I,WL(2)) - CALL MP_FFV1L_1(WL(2),W(WE(1),H),LC(1),ML(3),ZERO,WL(3)) - CALL MP_FFV1L_1(WL(3),W(WE(2),H),LC(2),ML(4),ZERO,WL(4)) - CALL MP_FFV1L_1(WL(4),W(WE(3),H),LC(3),ML(5),ZERO,WL(5)) - BUFF(I)=WL(5)%W(I) - ENDDO - CALL MP_CLOSE_4(BUFF(1),RES) - ENDIF - END - - SUBROUTINE ML5_0_MPLOOPNUM_DUMMY(Q,RES) -C -C ARGUMENTS -C - INCLUDE 'cts_mprec.h' - INCLUDE 'cts_mpc.h' - $ , INTENT(IN), DIMENSION(0:3) :: Q - INCLUDE 'cts_mpc.h' - $ , INTENT(OUT) :: RES -C -C LOCAL VARIABLES -C - COMPLEX*16 DRES - COMPLEX*16 DQ(0:3) - INTEGER I -C ---------- -C BEGIN CODE -C ---------- - DO I=0,3 - DQ(I) = Q(I) - ENDDO - - CALL ML5_0_LOOPNUM(DQ,DRES) - RES=DRES - - END - diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/makefile b/UNITTEST_proc/SubProcesses/P0_gg_ttx/makefile deleted file mode 120000 index cc63b08c84..0000000000 --- a/UNITTEST_proc/SubProcesses/P0_gg_ttx/makefile +++ /dev/null @@ -1 +0,0 @@ -../makefile \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/mg5_citation.f b/UNITTEST_proc/SubProcesses/P0_gg_ttx/mg5_citation.f deleted file mode 120000 index dad07bbaa4..0000000000 --- a/UNITTEST_proc/SubProcesses/P0_gg_ttx/mg5_citation.f +++ /dev/null @@ -1 +0,0 @@ -../mg5_citation.f \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/mp_born_amps_and_wfs.f b/UNITTEST_proc/SubProcesses/P0_gg_ttx/mp_born_amps_and_wfs.f deleted file mode 100644 index 7a036ee3d5..0000000000 --- a/UNITTEST_proc/SubProcesses/P0_gg_ttx/mp_born_amps_and_wfs.f +++ /dev/null @@ -1,282 +0,0 @@ - SUBROUTINE ML5_0_MP_BORN_AMPS_AND_WFS(P) - USE ALOHA_OBJECT -C -C Generated by MadGraph5_aMC@NLO v. 3.7.2, 2026-04-29 -C By the MadGraph5_aMC@NLO Development Team -C Visit launchpad.net/madgraph5 and amcatnlo.web.cern.ch -C -C Computes all the AMP and WFS in quadruple precision for the -C phase space point P(0:3,NEXTERNAL) -C -C Process: g g > t t~ QCD<=2 QED=0 [ virt = QCD ] -C - IMPLICIT NONE -C -C CONSTANTS -C - INTEGER NBORNAMPS - PARAMETER (NBORNAMPS=3) - INTEGER NLOOPAMPS, NCTAMPS - PARAMETER (NLOOPAMPS=129, NCTAMPS=85) - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INTEGER NWAVEFUNCS - PARAMETER (NWAVEFUNCS=10) - INTEGER NCOMB - PARAMETER (NCOMB=16) - REAL*16 ZERO - PARAMETER (ZERO=0E0_16) - COMPLEX*32 IMAG1 - PARAMETER (IMAG1=(0E0_16,1E0_16)) - -C -C ARGUMENTS -C - REAL*16 P(0:3,NEXTERNAL) -C -C LOCAL VARIABLES -C - INTEGER I,J,H - INTEGER NHEL(NEXTERNAL), IC(NEXTERNAL) - DATA IC/NEXTERNAL*1/ - INTEGER FLAVOR(NEXTERNAL) - DATA FLAVOR /NEXTERNAL*1/ -C -C FUNCTIONS -C - LOGICAL ML5_0_IS_HEL_SELECTED -C -C GLOBAL VARIABLES -C - INCLUDE 'mp_coupl_same_name.inc' - - INTEGER NTRY - LOGICAL CHECKPHASE,HELDOUBLECHECKED - REAL*8 REF - COMMON/ML5_0_INIT/NTRY,CHECKPHASE,HELDOUBLECHECKED,REF - - LOGICAL GOODHEL(NCOMB) - LOGICAL GOODAMP(NLOOPAMPS,NCOMB) - COMMON/ML5_0_FILTERS/GOODAMP,GOODHEL - - INTEGER HELPICKED - COMMON/ML5_0_HELCHOICE/HELPICKED - - COMPLEX*32 AMP(NBORNAMPS,NCOMB) - COMMON/ML5_0_MP_AMPS/AMP - COMPLEX*16 DPAMP(NBORNAMPS,NCOMB) - COMMON/ML5_0_AMPS/DPAMP - TYPE(MP_ALOHA) W(NWAVEFUNCS,NCOMB) - COMMON/ML5_0_MP_WFS/W - - COMPLEX*32 AMPL(3,NCTAMPS) - COMMON/ML5_0_MP_AMPL/AMPL - - TYPE(ALOHA) DPW(NWAVEFUNCS,NCOMB) - COMMON/ML5_0_WFCTS/DPW - - COMPLEX*16 DPAMPL(3,NLOOPAMPS) - LOGICAL S(NLOOPAMPS) - COMMON/ML5_0_AMPL/DPAMPL,S - - INTEGER HELC(NEXTERNAL,NCOMB) - COMMON/ML5_0_HELCONFIGS/HELC - - LOGICAL MP_DONE_ONCE - COMMON/ML5_0_MP_DONE_ONCE/MP_DONE_ONCE - -C This array specify potential special requirements on the -C helicities to -C consider. POLARIZATIONS(0,0) is -1 if there is not such -C requirement. - INTEGER POLARIZATIONS(0:NEXTERNAL,0:5) - COMMON/ML5_0_BEAM_POL/POLARIZATIONS - -C ---------- -C BEGIN CODE -C --------- - - MP_DONE_ONCE=.TRUE. - -C To be on the safe side, we always update the MP params here. -C It can be redundant as this routine can be called a couple of -C times for the same PS point during the stability checks. -C But it is really not time consuming and I would rather be safe. - CALL MP_UPDATE_AS_PARAM() - - DO H=1,NCOMB - IF ((HELPICKED.EQ.H).OR.((HELPICKED.EQ.-1) - $ .AND.((CHECKPHASE.OR..NOT.HELDOUBLECHECKED).OR.GOODHEL(H)))) - $ THEN -C Handle the possible requirement of specific polarizations - IF ((.NOT.CHECKPHASE) - $ .AND.HELDOUBLECHECKED.AND.POLARIZATIONS(0,0) - $ .EQ.0.AND.(.NOT.ML5_0_IS_HEL_SELECTED(H))) THEN - CYCLE - ENDIF - DO I=1,NEXTERNAL - NHEL(I)=HELC(I,H) - ENDDO - CALL MP_VXXXXX(P(0,1),ZERO,NHEL(1),-1,W(1,H)) - CALL MP_VXXXXX(P(0,2),ZERO,NHEL(2),-1,W(2,H)) - CALL MP_OXXXXX(P(0,3),MDL_MT,NHEL(3),+1, FLAVOR(3),W(3,H)) - CALL MP_IXXXXX(P(0,4),MDL_MT,NHEL(4),-1, FLAVOR(4),W(4,H)) - CALL MP_VVV1P0_1(W(1,H),W(2,H),GC_4,ZERO,ZERO,W(5,H)) -C Amplitude(s) for born diagram with ID 1 - CALL MP_FFV1_0(W(4,H),W(3,H),W(5,H),GC_5,AMP(1,H)) - CALL MP_FFV1_1(W(3,H),W(1,H),GC_5,MDL_MT,MDL_WT,W(6,H)) -C Amplitude(s) for born diagram with ID 2 - CALL MP_FFV1_0(W(4,H),W(6,H),W(2,H),GC_5,AMP(2,H)) - CALL MP_FFV1_2(W(4,H),W(1,H),GC_5,MDL_MT,MDL_WT,W(7,H)) -C Amplitude(s) for born diagram with ID 3 - CALL MP_FFV1_0(W(7,H),W(3,H),W(2,H),GC_5,AMP(3,H)) - CALL MP_FFV1P0_3(W(4,H),W(3,H),GC_5,ZERO,ZERO,W(8,H)) -C Counter-term amplitude(s) for loop diagram number 4 - CALL MP_R2_GG_1_R2_GG_2_0(W(5,H),W(8,H),R2_GGG_1,R2_GGG_2 - $ ,AMPL(1,1)) -C Counter-term amplitude(s) for loop diagram number 5 - CALL MP_FFV1_0(W(4,H),W(3,H),W(5,H),R2_GQQ,AMPL(1,2)) - CALL MP_FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQB_1EPS,AMPL(2,3)) - CALL MP_FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQB_1EPS,AMPL(2,4)) - CALL MP_FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQB_1EPS,AMPL(2,5)) - CALL MP_FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQB_1EPS,AMPL(2,6)) - CALL MP_FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQB_1EPS,AMPL(2,7)) - CALL MP_FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQB_1EPS,AMPL(2,8)) - CALL MP_FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQG_1EPS,AMPL(2,9)) - CALL MP_FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQB,AMPL(1,10)) - CALL MP_FFV1_0(W(4,H),W(3,H),W(5,H),UV_GQQT,AMPL(1,11)) - CALL MP_FFV1_2(W(4,H),W(2,H),GC_5,MDL_MT,MDL_WT,W(9,H)) -C Counter-term amplitude(s) for loop diagram number 7 - CALL MP_R2_QQ_1_R2_QQ_2_0(W(9,H),W(6,H),R2_QQQ,R2_QQT,AMPL(1 - $ ,12)) - CALL MP_R2_QQ_2_0(W(9,H),W(6,H),UV_TMASS_1EPS,AMPL(2,13)) - CALL MP_R2_QQ_2_0(W(9,H),W(6,H),UV_TMASS,AMPL(1,14)) -C Counter-term amplitude(s) for loop diagram number 8 - CALL MP_FFV1_0(W(4,H),W(6,H),W(2,H),R2_GQQ,AMPL(1,15)) - CALL MP_FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQB_1EPS,AMPL(2,16)) - CALL MP_FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQB_1EPS,AMPL(2,17)) - CALL MP_FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQB_1EPS,AMPL(2,18)) - CALL MP_FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQB_1EPS,AMPL(2,19)) - CALL MP_FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQB_1EPS,AMPL(2,20)) - CALL MP_FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQB_1EPS,AMPL(2,21)) - CALL MP_FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQG_1EPS,AMPL(2,22)) - CALL MP_FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQB,AMPL(1,23)) - CALL MP_FFV1_0(W(4,H),W(6,H),W(2,H),UV_GQQT,AMPL(1,24)) - CALL MP_FFV1_1(W(3,H),W(2,H),GC_5,MDL_MT,MDL_WT,W(10,H)) -C Counter-term amplitude(s) for loop diagram number 10 - CALL MP_R2_QQ_1_R2_QQ_2_0(W(7,H),W(10,H),R2_QQQ,R2_QQT - $ ,AMPL(1,25)) - CALL MP_R2_QQ_2_0(W(7,H),W(10,H),UV_TMASS_1EPS,AMPL(2,26)) - CALL MP_R2_QQ_2_0(W(7,H),W(10,H),UV_TMASS,AMPL(1,27)) -C Counter-term amplitude(s) for loop diagram number 11 - CALL MP_FFV1_0(W(7,H),W(3,H),W(2,H),R2_GQQ,AMPL(1,28)) - CALL MP_FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQB_1EPS,AMPL(2,29)) - CALL MP_FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQB_1EPS,AMPL(2,30)) - CALL MP_FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQB_1EPS,AMPL(2,31)) - CALL MP_FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQB_1EPS,AMPL(2,32)) - CALL MP_FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQB_1EPS,AMPL(2,33)) - CALL MP_FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQB_1EPS,AMPL(2,34)) - CALL MP_FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQG_1EPS,AMPL(2,35)) - CALL MP_FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQB,AMPL(1,36)) - CALL MP_FFV1_0(W(7,H),W(3,H),W(2,H),UV_GQQT,AMPL(1,37)) -C Counter-term amplitude(s) for loop diagram number 13 - CALL MP_FFV1_0(W(4,H),W(10,H),W(1,H),R2_GQQ,AMPL(1,38)) - CALL MP_FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQB_1EPS,AMPL(2,39)) - CALL MP_FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQB_1EPS,AMPL(2,40)) - CALL MP_FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQB_1EPS,AMPL(2,41)) - CALL MP_FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQB_1EPS,AMPL(2,42)) - CALL MP_FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQB_1EPS,AMPL(2,43)) - CALL MP_FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQB_1EPS,AMPL(2,44)) - CALL MP_FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQG_1EPS,AMPL(2,45)) - CALL MP_FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQB,AMPL(1,46)) - CALL MP_FFV1_0(W(4,H),W(10,H),W(1,H),UV_GQQT,AMPL(1,47)) -C Counter-term amplitude(s) for loop diagram number 14 - CALL MP_FFV1_0(W(9,H),W(3,H),W(1,H),R2_GQQ,AMPL(1,48)) - CALL MP_FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQB_1EPS,AMPL(2,49)) - CALL MP_FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQB_1EPS,AMPL(2,50)) - CALL MP_FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQB_1EPS,AMPL(2,51)) - CALL MP_FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQB_1EPS,AMPL(2,52)) - CALL MP_FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQB_1EPS,AMPL(2,53)) - CALL MP_FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQB_1EPS,AMPL(2,54)) - CALL MP_FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQG_1EPS,AMPL(2,55)) - CALL MP_FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQB,AMPL(1,56)) - CALL MP_FFV1_0(W(9,H),W(3,H),W(1,H),UV_GQQT,AMPL(1,57)) -C Counter-term amplitude(s) for loop diagram number 17 - CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),R2_3GG,AMPL(1,58)) - CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GB_1EPS,AMPL(2,59)) - CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GB_1EPS,AMPL(2,60)) - CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GB_1EPS,AMPL(2,61)) - CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GB_1EPS,AMPL(2,62)) - CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GB_1EPS,AMPL(2,63)) - CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GB_1EPS,AMPL(2,64)) - CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GG_1EPS,AMPL(2,65)) - CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GB,AMPL(1,66)) - CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),UV_3GT,AMPL(1,67)) -C Counter-term amplitude(s) for loop diagram number 31 - CALL MP_R2_GG_1_0(W(5,H),W(8,H),R2_GGQ,AMPL(1,68)) - CALL MP_R2_GG_1_0(W(5,H),W(8,H),R2_GGQ,AMPL(1,69)) - CALL MP_R2_GG_1_0(W(5,H),W(8,H),R2_GGQ,AMPL(1,70)) - CALL MP_R2_GG_1_0(W(5,H),W(8,H),R2_GGQ,AMPL(1,71)) -C Counter-term amplitude(s) for loop diagram number 32 - CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),R2_3GQ,AMPL(1,72)) - CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),R2_3GQ,AMPL(1,73)) - CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),R2_3GQ,AMPL(1,74)) - CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),R2_3GQ,AMPL(1,75)) -C Counter-term amplitude(s) for loop diagram number 34 - CALL MP_R2_GG_1_R2_GG_3_0(W(5,H),W(8,H),R2_GGQ,R2_GGB,AMPL(1 - $ ,76)) -C Counter-term amplitude(s) for loop diagram number 35 - CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),R2_3GQ,AMPL(1,77)) -C Counter-term amplitude(s) for loop diagram number 37 - CALL MP_R2_GG_1_R2_GG_3_0(W(5,H),W(8,H),R2_GGQ,R2_GGT,AMPL(1 - $ ,78)) -C Counter-term amplitude(s) for loop diagram number 38 - CALL MP_VVV1_0(W(1,H),W(2,H),W(8,H),R2_3GQ,AMPL(1,79)) -C Amplitude(s) for UVCT diagram with ID 40 - CALL MP_FFV1_0(W(4,H),W(3,H),W(5,H),GC_5,AMPL(2,80)) - AMPL(2,80)=AMPL(2,80)*(4.0D0*UVWFCT_G_1_1EPS+2.0D0 - $ *UVWFCT_B_0_1EPS) -C Amplitude(s) for UVCT diagram with ID 41 - CALL MP_FFV1_0(W(4,H),W(3,H),W(5,H),GC_5,AMPL(1,81)) - AMPL(1,81)=AMPL(1,81)*(2.0D0*UVWFCT_G_1+2.0D0*UVWFCT_G_2 - $ +2.0D0*UVWFCT_T_0) -C Amplitude(s) for UVCT diagram with ID 42 - CALL MP_FFV1_0(W(4,H),W(6,H),W(2,H),GC_5,AMPL(2,82)) - AMPL(2,82)=AMPL(2,82)*(4.0D0*UVWFCT_G_1_1EPS+2.0D0 - $ *UVWFCT_B_0_1EPS) -C Amplitude(s) for UVCT diagram with ID 43 - CALL MP_FFV1_0(W(4,H),W(6,H),W(2,H),GC_5,AMPL(1,83)) - AMPL(1,83)=AMPL(1,83)*(2.0D0*UVWFCT_G_1+2.0D0*UVWFCT_G_2 - $ +2.0D0*UVWFCT_T_0) -C Amplitude(s) for UVCT diagram with ID 44 - CALL MP_FFV1_0(W(7,H),W(3,H),W(2,H),GC_5,AMPL(2,84)) - AMPL(2,84)=AMPL(2,84)*(4.0D0*UVWFCT_G_1_1EPS+2.0D0 - $ *UVWFCT_B_0_1EPS) -C Amplitude(s) for UVCT diagram with ID 45 - CALL MP_FFV1_0(W(7,H),W(3,H),W(2,H),GC_5,AMPL(1,85)) - AMPL(1,85)=AMPL(1,85)*(2.0D0*UVWFCT_G_1+2.0D0*UVWFCT_G_2 - $ +2.0D0*UVWFCT_T_0) -C Copy the qp wfs to the dp ones as they are used to setup the -C CT calls. - DO I=1,NWAVEFUNCS - DO J=1,SIZE(W(I,H)%W) - DPW(I,H)%W(J)=W(I,H)%W(J) - ENDDO - DPW(I,H)%P = W(I,H)%P - DPW(I,H)%FLV_INDEX = W(I,H)%FLV_INDEX - ENDDO -C Same for the counterterms amplitudes - DO I=1,NCTAMPS - DO J=1,3 - DPAMPL(J,I)=AMPL(J,I) - S(I)=.TRUE. - ENDDO - ENDDO - DO I=1,NBORNAMPS - DPAMP(I,H)=AMP(I,H) - ENDDO - ENDIF - ENDDO - - END - diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/mp_coupl.inc b/UNITTEST_proc/SubProcesses/P0_gg_ttx/mp_coupl.inc deleted file mode 120000 index bd73d507b2..0000000000 --- a/UNITTEST_proc/SubProcesses/P0_gg_ttx/mp_coupl.inc +++ /dev/null @@ -1 +0,0 @@ -../mp_coupl.inc \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/mp_coupl_same_name.inc b/UNITTEST_proc/SubProcesses/P0_gg_ttx/mp_coupl_same_name.inc deleted file mode 120000 index 819d1f1826..0000000000 --- a/UNITTEST_proc/SubProcesses/P0_gg_ttx/mp_coupl_same_name.inc +++ /dev/null @@ -1 +0,0 @@ -../mp_coupl_same_name.inc \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/nexternal.inc b/UNITTEST_proc/SubProcesses/P0_gg_ttx/nexternal.inc deleted file mode 100644 index f50affaedb..0000000000 --- a/UNITTEST_proc/SubProcesses/P0_gg_ttx/nexternal.inc +++ /dev/null @@ -1,4 +0,0 @@ - INTEGER NEXTERNAL - PARAMETER (NEXTERNAL=4) - INTEGER NINCOMING - PARAMETER (NINCOMING=2) diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/ngraphs.inc b/UNITTEST_proc/SubProcesses/P0_gg_ttx/ngraphs.inc deleted file mode 100644 index f6b2b0b7ac..0000000000 --- a/UNITTEST_proc/SubProcesses/P0_gg_ttx/ngraphs.inc +++ /dev/null @@ -1,2 +0,0 @@ - INTEGER N_MAX_CG - PARAMETER (N_MAX_CG=176) diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/nsquaredSO.inc b/UNITTEST_proc/SubProcesses/P0_gg_ttx/nsquaredSO.inc deleted file mode 100644 index 8060bbf5e8..0000000000 --- a/UNITTEST_proc/SubProcesses/P0_gg_ttx/nsquaredSO.inc +++ /dev/null @@ -1,2 +0,0 @@ - INTEGER NSQUAREDSO - PARAMETER (NSQUAREDSO=0) diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/pmass.inc b/UNITTEST_proc/SubProcesses/P0_gg_ttx/pmass.inc deleted file mode 100644 index a16f00b86d..0000000000 --- a/UNITTEST_proc/SubProcesses/P0_gg_ttx/pmass.inc +++ /dev/null @@ -1,4 +0,0 @@ - PMASS(1)=ZERO - PMASS(2)=ZERO - PMASS(3)=ABS(MDL_MT) - PMASS(4)=ABS(MDL_MT) diff --git a/UNITTEST_proc/SubProcesses/P0_gg_ttx/unique_id.inc b/UNITTEST_proc/SubProcesses/P0_gg_ttx/unique_id.inc deleted file mode 100644 index 534d4d1b58..0000000000 --- a/UNITTEST_proc/SubProcesses/P0_gg_ttx/unique_id.inc +++ /dev/null @@ -1,2 +0,0 @@ - integer UNIQUE_ID - parameter(UNIQUE_ID=1) \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/coupl.inc b/UNITTEST_proc/SubProcesses/coupl.inc deleted file mode 120000 index 06a93d2f15..0000000000 --- a/UNITTEST_proc/SubProcesses/coupl.inc +++ /dev/null @@ -1 +0,0 @@ -../Source/MODEL/coupl.inc \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/cts_mpc.h b/UNITTEST_proc/SubProcesses/cts_mpc.h deleted file mode 100644 index 803584d2de..0000000000 --- a/UNITTEST_proc/SubProcesses/cts_mpc.h +++ /dev/null @@ -1,2 +0,0 @@ - COMPLEX(KIND=16) - diff --git a/UNITTEST_proc/SubProcesses/cts_mprec.h b/UNITTEST_proc/SubProcesses/cts_mprec.h deleted file mode 100644 index 39ae82ac4c..0000000000 --- a/UNITTEST_proc/SubProcesses/cts_mprec.h +++ /dev/null @@ -1,2 +0,0 @@ - USE MPMODULE - diff --git a/UNITTEST_proc/SubProcesses/makefile b/UNITTEST_proc/SubProcesses/makefile deleted file mode 100644 index 64aeb77941..0000000000 --- a/UNITTEST_proc/SubProcesses/makefile +++ /dev/null @@ -1,201 +0,0 @@ - -ifeq ($(wildcard ../Source/make_opts),) - ifeq ($(wildcard ../../Source/make_opts),) - ROOT = ../../.. - else - ROOT = ../.. - endif -else - ROOT = .. -endif -LIBDIR = $(abspath $(ROOT))/lib/ - -PROG = check -all : $(PROG) - -HERE := $(dir $(abspath $(firstword $(MAKEFILE_LIST)))) -ROOTNAME = $(notdir $(abspath $(ROOT))) - -# For the compilation of the MadLoop file polynomial.f it makes a big difference to use -O3 and -# to turn off the bounds check. These can however be modified here if really necessary. -POLYNOMIAL_OPTIMIZATION = -O3 -POLYNOMIAL_BOUNDS_CHECK = - -include $(ROOT)/Source/make_opts -FFLAGS += -I$(ROOT)/Source/MODEL -I$(ROOT)/Source/DHELAS -include $(ROOT)/SubProcesses/MadLoop_makefile_definitions -SHELL = /bin/bash - -OLP = OLP -STABCHECKDRIVER = StabilityCheckDriver -CHECK_SA_BORN_SPLITORDERS = check_sa_born_splitOrders -LINKLIBS = -L$(LIBDIR) -ldhelas -lmodel $(LINK_LOOP_LIBS) $(LDFLAGS) -LIBS = $(LIBDIR)libdhelas.$(libext) $(LIBDIR)libmodel.$(libext) $(LOOP_LIBS) -DYLIBS = $(LIBDIR)libdhelas.$(dylibext) $(LIBDIR)libmodel.$(dylibext) $(LOOP_LIBS) - -PROCESS= MadLoopParamReader.o MadLoopCommons.o \ - $(patsubst $(DOTF),$(DOTO),$(wildcard polynomial.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard loop_matrix.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard improve_ps.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard born_matrix.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard CT_interface.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard loop_num.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard helas_calls*.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard jamp?_calls_*.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard mp_born_amps_and_wfs.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard mp_compute_loop_coefs.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard mp_helas_calls*.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard coef_construction_*.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard loop_CT_calls_*.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard mp_coef_construction_*.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard TIR_interface.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard GOLEM_interface.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard COLLIER_interface.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard compute_color_flows.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard mg5_citation.f)) - -OLP_PROCESS= MadLoopParamReader.o MadLoopCommons.o \ - $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/polynomial.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/loop_matrix.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/improve_ps.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/born_matrix.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/CT_interface.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/loop_num.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/helas_calls*.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/jamp?_calls_*.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/mp_born_amps_and_wfs.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/mp_compute_loop_coefs.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/mp_helas_calls*.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/coef_construction_*.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/loop_CT_calls_*.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/mp_coef_construction_*.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/TIR_interface.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/GOLEM_interface.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/COLLIER_interface.f)) \ - $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/compute_color_flows.f)) - -POLYNOMIAL = $(patsubst $(DOTF),$(DOTO),$(wildcard polynomial.f)) -OLP_POLYNOMIAL = $(patsubst $(DOTF),$(DOTO),$(wildcard $(LOOP_PREFIX)*/polynomial.f)) - - - -$(PROG): check_sa.o $(PROCESS) makefile $(LIBS) libcollier.$(dylibext) - $(FC) $(FFLAGS) -o $(PROG) check_sa.o $(PROCESS) $(LINKLIBS) - -$(STABCHECKDRIVER): StabilityCheckDriver.o $(PROCESS) makefile $(LIBS) - $(FC) $(FFLAGS) -o $(STABCHECKDRIVER) StabilityCheckDriver.o $(PROCESS) $(LINKLIBS) - -# The program below is not essential but just an helpful one to run the born only -$(CHECK_SA_BORN_SPLITORDERS): check_sa_born_splitOrders.o $(patsubst $(DOTF),$(DOTO),$(wildcard *born_matrix.f)) makefile $(LIBDIR)libdhelas.$(libext) $(LIBDIR)libmodel.$(libext) - $(FC) $(FFLAGS) -o $(CHECK_SA_BORN_SPLITORDERS) check_sa_born_splitOrders.o $(patsubst $(DOTF),$(DOTO),$(wildcard *born_matrix.f)) -L$(LIBDIR) -ldhelas -lmodel - -# This is the core of madloop computationally wise, so make sure to turn optimizations on and bound checks off. -# We use %olynomial.o and not directly polynomial.o because we want it to match when both doing make check here -# or make OLP one directory above -%oloop_matrix.o : %olynomial.o %oloop_matrix.f -%olynomial.o : %olynomial.f - $(FC) $(patsubst -O%,, $(subst -fbounds-check,,$(FFLAGS))) $(POLYNOMIAL_OPTIMIZATION) $(POLYNOMIAL_BOUNDS_CHECK) -c $< -o $@ $(LOOP_INCLUDE) - -%/%oloop_matrix.o : %/polynomial.o %/%oloop_matrix.f - $(FC) $(patsubst -O%,,$(subst -fbounds-check,,$(FFLAGS))) \ - $(POLYNOMIAL_OPTIMIZATION) $(POLYNOMIAL_BOUNDS_CHECK) \ - -c $< -o $@ $(LOOP_INCLUDE) - -%/polynomial.o : %/polynomial.f - $(FC) $(patsubst -O%,,$(subst -fbounds-check,,$(FFLAGS))) \ - $(POLYNOMIAL_OPTIMIZATION) $(POLYNOMIAL_BOUNDS_CHECK) \ - -c $< -o $@ $(LOOP_INCLUDE) - - -$(DOTO) : $(DOTF) $(POLYNOMIAL) $(OLP_POLYNOMIAL) - $(FC) $(FFLAGS) -c $< -o $@ $(LOOP_INCLUDE) - -$(DOTO) : $(DOTF) - $(FC) $(FFLAGS) -c $< -o $@ $(LOOP_INCLUDE) - -$(OLP): $(OLP_PROCESS) $(LIBS) mg5_citation.o - $(FC) -shared $(OLP_PROCESS) mg5_citation.o -o libMadLoop.$(dylibext) $(LINKLIBS) - -$(OLP)_static: $(OLP_PROCESS) - ar rcs libMadLoop.$(libext) $(OLP_PROCESS) - mv libMadLoop.$(libext) $(MADLOOP_LIB) - -../$(OLP): - rm -f libMadLoop.$(dylibext) - ln -s ../libMadLoop.$(dylibext) - cd $(ROOT)/SubProcesses; make $(OLP) - -../$(OLP)_static: - cd $(ROOT)/SubProcesses; make $(OLP)_static - -libMadLoop.$(dylibext): ../$(OLP) - -WRAPPER_SRCS := $(wildcard */f2py_wrapper.f) -WRAPPER_OBJS := $(patsubst %.f,%.o,$(wildcard */f2py_wrapper.f)) - -%/f2py_wrapper.o: %/f2py_wrapper.f - $(MAKE) -C $* f2py_wrapper.o - - - - -ALL_DOTF := $(wildcard */polynomial.f */loop_matrix.f */improve_ps.f */born_matrix.f */CT_interface.f \ - */loop_num.f \ - */helas_calls*.f */mp_compute_loop_coefs.f */mp_helas_calls*.f */coef_construction_*.f \ - */loop_CT_calls_*.f */mp_coef_construction_*.f */TIR_interface.f */COLLIER_interface.f \ - MadLoopParamReader.f MadLoopCommons.f mg5_citation.f */GOLEM_interface.f */compute_color_flows.f \ - */mp_born_amps_and_wfs.f */jamp?_calls_*.f) - -# Convert .f to .o -ALL_DOTO := $(patsubst %.f,%.o,$(ALL_DOTF)) - -ifeq ($(UNAME), Darwin) - LIBALLME_DYNFLAG = -install_name @rpath/liball$(ROOTNAME)_$(MENUM)me.dylib -undefined dynamic_lookup - WHOLE_ARCH=-Wl,-force_load, - NOWHOLE_ARCH= - STAT_LIB = $(WHOLE_ARCH)$(LIBDIR)libcts.$(libext) $(WHOLE_ARCH)$(LIBDIR)libiregi.$(libext) - LD_F2PY= -else - LIBALLME_DYNFLAG = - WHOLE_ARCH= -Wl,--whole-archive - NOWHOLE_ARCH= -Wl,--no-whole-archive - STAT_LIB = $(WHOLE_ARCH) $(LIBDIR)libcts.$(libext) $(LIBDIR)libiregi.$(libext) $(NOWHOLE_ARCH) - LD_F2PY=-lgfortran -lquadmath -endif - -ifeq ($(origin MENUM),undefined) - MENUM=2 -endif - -liball$(ROOTNAME)_$(MENUM)me.$(dylibext): all_matrix.o libMadLoop.$(dylibext) $(WRAPPER_OBJS) $(LIBS) $(OLP) - $(CXX) $(DYNLIBFLAG) $(LIBALLME_DYNFLAG) $(STDLIB_FLAG) -o liball$(ROOTNAME)_$(MENUM)me.$(dylibext) all_matrix.o */f2py_wrapper.o ../Source/DHELAS/*.o ../Source/MODEL/*.o $(STAT_LIB) $(RPATH_LIBS) $(LINK_LOOP_LIBS) $(ALL_DOTO) $(STDLIB) $(LINK_LOOP_LIBS) - - - -libcollier.$(dylibext): - ln -s $(LIBDIR)/collier_lib/libcollier.$(dylibext) || echo "libcolier already linked" - - - -shared: liball$(ROOTNAME)_$(MENUM)me.$(dylibext) - - - - -matrix$(MENUM)py.so: ../$(OLP)_static f2py_wrapper.f - touch __init__.py - $(F2PY) $(MADLOOP_LIB) -m matrix$(MENUM)py -c f2py_wrapper.f --f77exec=$(FC) -L../../lib/ -ldhelas -lmodel $(LINK_LOOP_LIBS) $(STDLIB) - -allmatrix$(MENUM)py.so: $(OLP)_static all_matrix.f $(LIBS) $(WRAPPER) - touch __init__.py - $(F2PY) $(MADLOOP_LIB) -m allmatrix$(MENUM)py -c all_matrix.f $(wildcard $(LOOP_PREFIX)*/f2py_wrapper.f) --f77exec=$(FC) -L../lib/ -ldhelas -lmodel $(LINK_LOOP_LIBS) $(STDLIB) - - -all_matrix$(MENUM)py.so: liball$(ROOTNAME)_$(MENUM)me.$(dylibext) f2py_wrapper.f makefile - LDFLAGS="-Wl,-rpath,$(HERE) -L$(HERE) $(RPATH_LIBS) $(LINK_LOOP_LIBS) $(LD_F2PY)" $(F2PY) -c f2py_wrapper.f -L$(HERE) -lall$(ROOTNAME)_$(MENUM)me -m all_matrix$(MENUM)py - touch all_matrix$(MENUM)py.so - touch __init__.py - - -clean: - @rm -f *.o *.so *.$(libext) *.$(dylibext) diff --git a/UNITTEST_proc/SubProcesses/makefileP b/UNITTEST_proc/SubProcesses/makefileP deleted file mode 100644 index ad47e08a27..0000000000 --- a/UNITTEST_proc/SubProcesses/makefileP +++ /dev/null @@ -1,55 +0,0 @@ -include ../../Source/make_opts -SHELL = /bin/bash -HERE := $(dir $(abspath $(firstword $(MAKEFILE_LIST)))) -ROOT_DIR = $(HERE)/../../ -LIBDIR := $(abspath $(HERE)/../../lib) -PDIR := $(strip $(notdir $(patsubst %/,%,$(strip $(HERE))))) -PROG = check -# Absolute path to the process directory; used as an include path so that the -# Fortran compiler can locate process-local .inc files when matrix.f is built -# from a different cwd (needed for python3.12/3.13 / f2py setups). -# Keep this distinct from PDIR (basename) which is used for dylib naming below. -PDIR_FULL:=$(shell dirname $(realpath --no-symlinks $(firstword matrix.f))) -PROG_SPLITORDERS = check_sa_born_splitOrders -LINKLIBS = -L$(LIBDIR) -ldhelas -lmodel -LIBS = $(LIBDIR)/libdhelas.$(libext) $(LIBDIR)/libmodel.$(libext) -LIBS_SHARED = $(LIBDIR)/libdhelas.$(dylibext) $(LIBDIR)/libmodel.$(dylibext) -PROCESS= matrix.o -CHECK_SA= check_sa.o -CHECK_SA_SPLITORDERS= check_sa_born_splitOrders.o - -F_INCLUDE = -I$(ROOT_DIR)/Source/DHELAS -I$(ROOT_DIR)/Source/MODEL -I$(PDIR_FULL) -FFLAGS += $(F_INCLUDE) - -$(PROG): $(LIBS) $(PROCESS) $(CHECK_SA) makefile - $(FC) $(FFLAGS) -o $(PROG) $(PROCESS) $(CHECK_SA) $(LINKLIBS) - -$(PROG_SPLITORDERS): $(PROCESS) $(CHECK_SA_SPLITORDERS) makefile $(LIBS) - $(FC) $(FFLAGS) -o $(PROG) $(PROCESS) $(CHECK_SA_SPLITORDERS) $(LINKLIBS) - -driver.f: nexternal.inc pmass.inc ngraphs.inc coupl.inc - -$(LIBDIR)/libdhelas.$(libext): - $(MAKE) -C "$(LIBDIR)/../Source/DHELAS" -$(LIBDIR)/libmodel.$(libext): - $(MAKE) -C "$(LIBDIR)/../Source/DHELAS" -$(LIBDIR)/libdhelas.$(dylibext): - $(MAKE) -C "$(LIBDIR)/../Source/DHELAS" shared -$(LIBDIR)/libmodel.$(dylibext): - $(MAKE) -C "$(LIBDIR)/../Source/MODEL" shared - -# For python linking (require f2py part of numpy) -ifeq ($(origin MENUM),undefined) - MENUM=2 -endif - -libme$(PDIR).$(dylibext): $(LIBDIR)/libdhelas.$(dylibext) $(LIBDIR)/libmodel.$(dylibext) matrix.o - gfortran $(DYNLIBFLAG) $(RPATHFLAG)libme$(PDIR).$(dylibext) -o libme$(PDIR).$(dylibext) matrix.o ../../Source/DHELAS/*.o ../../Source/MODEL/*.o - -matrix$(MENUM)py.so: f2py_matrix_wrapper.f libme$(PDIR).$(dylibext) makefile - touch __init__.py - LDFLAGS="-Wl,-rpath,$(HERE)" $(F2PY) -c f2py_matrix_wrapper.f -L$(HERE) -lme$(PDIR) $(LINKLIBS) -m matrix$(MENUM)py - touch matrix$(MENUM)py.so - cp $(LIBDIR)/*$(dylibext) . - - diff --git a/UNITTEST_proc/SubProcesses/mg5_citation.f b/UNITTEST_proc/SubProcesses/mg5_citation.f deleted file mode 100644 index 8bd4953454..0000000000 --- a/UNITTEST_proc/SubProcesses/mg5_citation.f +++ /dev/null @@ -1,91 +0,0 @@ - subroutine cite(key, context) -c*********************************************************************** -c Record that the reference identified by the INSPIRE texkey `key` -c was used by this run, optionally for the purpose described by the -c free-text `context`. -c -c Each call appends a single line -c keycontext -c to the per-process file -c $MG5_CITATION_DIR/cite...log -c (de-duplicated within the process). The orchestrating Python layer -c collects every such file at the end of the run and turns them into a -c ready-to-use citations.bib together with a human-readable summary. -c -c A per-process file name means there is never a cross-process write -c race, on any filesystem. When MG5_CITATION_DIR is unset the routine -c is a silent no-op, so it is safe to call unconditionally. Any I/O -c failure is swallowed: citation tracking must never abort a run. -c*********************************************************************** - implicit none -c -c Arguments -c - character*(*) key, context -c -c Local parameters -c - integer maxcite - parameter (maxcite=500) - integer reclen - parameter (reclen=320) -c -c Saved per-process state (the keys already written) -c - character*(reclen) seen(maxcite) - integer nseen - save seen, nseen - data nseen /0/ -c -c Local variables -c - character*512 cdir - character*1024 fname - character*(reclen) record - character*256 host - integer dirlen, st, pid, i, lun - logical used -c -c----- -c Begin Code -c----- -c enabled only when MG5_CITATION_DIR points somewhere - call get_environment_variable('MG5_CITATION_DIR', - & cdir, dirlen, st) - if (dirlen .le. 0) return - if (dirlen .gt. len(cdir)) return -c -c the de-duplication record is keycontext - record = trim(key)//char(9)//trim(context) -c -c guard the shared state/file against OpenMP threads of this process -c$omp critical (mg5_cite) - used = .false. - do i = 1, nseen - if (seen(i) .eq. record) used = .true. - enddo -c - if (.not. used) then - if (nseen .lt. maxcite) then - nseen = nseen + 1 - seen(nseen) = record - endif -c build /cite...log - host = 'localhost' - call hostnm(host, st) - pid = getpid() - write(fname, '(a,a,a,a,i0,a)') cdir(1:dirlen), - & '/cite.', trim(host), '.', pid, '.log' -c append the record, swallowing any failure - lun = 87 - open(unit=lun, file=fname, status='unknown', - & position='append', iostat=st) - if (st .eq. 0) then - write(lun, '(a)', iostat=st) trim(record) - close(lun) - endif - endif -c$omp end critical (mg5_cite) -c - return - end diff --git a/UNITTEST_proc/SubProcesses/mp_coupl.inc b/UNITTEST_proc/SubProcesses/mp_coupl.inc deleted file mode 120000 index 8b7845362c..0000000000 --- a/UNITTEST_proc/SubProcesses/mp_coupl.inc +++ /dev/null @@ -1 +0,0 @@ -../Source/MODEL/mp_coupl.inc \ No newline at end of file diff --git a/UNITTEST_proc/SubProcesses/mp_coupl_same_name.inc b/UNITTEST_proc/SubProcesses/mp_coupl_same_name.inc deleted file mode 120000 index 8bb4c2a03f..0000000000 --- a/UNITTEST_proc/SubProcesses/mp_coupl_same_name.inc +++ /dev/null @@ -1 +0,0 @@ -../Source/MODEL/mp_coupl_same_name.inc \ No newline at end of file diff --git a/UNITTEST_proc/TemplateVersion.txt b/UNITTEST_proc/TemplateVersion.txt deleted file mode 100644 index 437459cd94..0000000000 --- a/UNITTEST_proc/TemplateVersion.txt +++ /dev/null @@ -1 +0,0 @@ -2.5.0 From 7c446c27318fe2553195e56d1bb80953db924443 Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 13:38:50 +0200 Subject: [PATCH 22/39] measure what the diagram order is worth, and why it is not shipped yet reuse_outdated_wavefunctions is a linear scan allocator over lifetimes in emission order, so NWAVEFUNCS depends on the diagram order -- the wavefunction set does not, being content addressed, but the slot count does. Emitting every seed first, as the expansion does, is the worst case for it. Placing each diagram at its last discovery rather than its first takes both the locality and the sums: 27 slots instead of 66 at six gluons, below the 51 of the unoptimised code, with all 30 sums kept, and Fortran exact at N=2..5. Not shipped because it makes g g > g g g g wrong in madmatrix, which has duplicate wavefunction listings that a directly built matrix element does not. Co-Authored-By: Claude Opus 5 --- docs/gluon-quartic-plan.md | 40 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/docs/gluon-quartic-plan.md b/docs/gluon-quartic-plan.md index 121a55728b..0525c90ae7 100644 --- a/docs/gluon-quartic-plan.md +++ b/docs/gluon-quartic-plan.md @@ -414,6 +414,46 @@ turns positive from six gluons on. and seven, in both backends. With the flag off, `matrix.f` and `CPPProcess.cc` are byte-identical to before any of this. +## The diagram order — measured, and worth a lot + +`reuse_outdated_wavefunctions` is a linear scan allocator over lifetimes taken +in **emission order**, so `NWAVEFUNCS` depends on the order the diagrams are +written in. (The wavefunction *set* does not — that is content addressed, +`wavefunctions[wavefunctions.index(new_wf)]` — but the number of slots very +much does.) The shipped expansion emits every seed first and then the +unrollings, which is the worst case for it: a quartic current is made early +and its sum is not consumed until much later. + +Four orders were built and run. A sum can only be formed when its quartic +current is emitted before the target amplitude, which is what makes this a +trade rather than a free win: + +| `NWAVEFUNCS` / sums | off | seeds first (shipped) | by quartic count | seed then its own unrollings | last discovery | +|---|---|---|---|---|---| +| `g g > g g g` | 12 | 19 / 7 | 19 / 7 | 11 / 3 | **15 / 7** | +| `g g > g g g g` | 51 | 66 / 30 | 64 / 30 | 33 / **0** | **27 / 30** | +| `g g > 5 g` | 268 | 290 / 60 | 314 / 60 | 245 / 60 | **219 / 60** | + +Emitting a seed followed by its own unrollings gives the locality but loses +the sums: the fully cubic target is usually claimed by an earlier seed, so the +quartic current arrives after it. **Placing each diagram at its *last* +discovery instead of its first fixes that** — the target then sits after every +seed which can reach it — and takes both: all the sums, and a slot count +*below* the flag off baseline (27 against 51 at six gluons, 219 against 268 at +seven). + +It is not shipped, because it makes `g g > g g g g` come out **wrong in +madmatrix** (2.43e-04 against 1.59e-04) while Fortran stays exact at N=2..5. +The generated code has no read before write, and a matrix element built +directly has no duplicate wavefunction listings — those appear only through +the madmatrix exporter path, which is also what forced the `allocated` guard +in step 8. So the reordering is exposing something latent on that side rather +than being wrong itself, but that has to be understood before it can go in. + +Worth doing: at six gluons it would take the wavefunction store from 6600 B to +2700 B, *under* the 5100 B of the unoptimised code, with every current sum +kept. + ## Where to go next **Give madmatrix the amplitude sums too.** It is the only backend without From cd18597d983035a5a486612818be9ca8cfad90fe Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 14:09:52 +0200 Subject: [PATCH 23/39] add the madmatrix seven gluon row g g > 5 g in madmatrix finally finished compiling: 41.75 -> 43.33 evt/s, +3.8%, with nwf 268 -> 320 and |M|^2 agreeing to 1.6e-15. The generated CPPProcess.cc was checked byte-identical against what the committed code produces, since the build had been launched before the ordering experiments. Co-Authored-By: Claude Opus 5 --- docs/gluon-quartic-plan.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/gluon-quartic-plan.md b/docs/gluon-quartic-plan.md index 0525c90ae7..d376681c38 100644 --- a/docs/gluon-quartic-plan.md +++ b/docs/gluon-quartic-plan.md @@ -377,7 +377,7 @@ hide any difference). Two runs each, reproducible to about 0.1%. | `g g > g g` | 11.00 -> 11.04 s | -0.4% | 875150 -> 878724 | +0.4% | | `g g > g g g` | 34.90 -> 34.99 s | -0.3% | 72359 -> 66757 | **-7.7%** | | `g g > g g g g` | 47.35 -> 45.61 s | **+3.7%** | 2699 -> 2784 | **+3.1%** | -| `g g > 5 g` | 43.05 -> 39.98 s | **+7.1%** | not measured | | +| `g g > 5 g` | 43.05 -> 39.98 s | **+7.1%** | 41.75 -> 43.33 | **+3.8%** | Four gluons is a wash on both (there is nothing to sum: the only quartic vertex is the whole amplitude). Five gluons loses on madmatrix, where the @@ -397,9 +397,10 @@ Fortran (4 complex, 4 reals, one int) and 192 in madmatrix on sse4 in double | `g g > 5 g` | 268 | 321 | **290** | 29000 B (+8%) | madmatrix carries duplicate wavefunctions of its own, so its count with the -flag on is higher: 19 / 86 at five and six gluons, against 19 / 66 in Fortran. -The relative cost falls as the multiplicity rises, which is why the trade -turns positive from six gluons on. +flag on is higher: 19 / 86 / 320 at five, six and seven gluons, against +19 / 66 / 290 in Fortran. The relative cost falls as the multiplicity rises +(+58% at five gluons, +19% at seven), which is why the trade turns positive +from six gluons on. **Work done per call** @@ -408,7 +409,7 @@ turns positive from six gluons on. | `g g > g g` | 29 -> 29 | 23 -> 20 | 6 -> 6 | 34 -> 34 | | `g g > g g g` | 94 -> 100 (+7 sums) | 131 -> 101 | 45 -> 38 | 370 -> 314 | | `g g > g g g g` | 637 -> 642 (+30) | 1082 -> 688 | 510 -> 450 | 8170 -> 7210 | -| `g g > 5 g` | 8159 -> 7844 (+60) | 23672 -> 7864 | | | +| `g g > 5 g` | 8159 -> 7844 (+60) | 23672 -> 7864 | 7245 -> 6813 | 231850 -> 218026 | `|M|^2` is bit-identical at four and five gluons and agrees to 1e-14 at six and seven, in both backends. With the flag off, `matrix.f` and `CPPProcess.cc` From 65c457fd629c6b4b084de8650700115df73b549c Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 15:56:32 +0200 Subject: [PATCH 24/39] check the colour structure when pairing a quartic current with a cubic one is_unrolled_pair matched on the lines alone: same four coming in, same one going out. A quartic vertex makes one current per colour structure and all three take the same lines and make the same line, so the lines cannot tell them apart -- only the pairing can, read against sorted_mothers. Nothing moves on the shipped ordering (same 7/30/60 sums, same |M|^2 in both backends), but it removes a class of mismatch which was only not biting by luck. Also records where the reordering breaks madmatrix. Ruled out by measurement: the reordering itself, slot corruption, coloramps.h, the merge_quartic_amplitudes=False path, and the duplicate listings on their own. What is left, from replaying both generated files symbolically: the folding is ordering sensitive in madmatrix (40 of 450 amplitudes differ) and not in Fortran (0 of 450). madmatrix carries two objects for the same current and match_quartic_mothers compares mothers by number, so which copy an amplitude holds decides which pairs are matched. Co-Authored-By: Claude Opus 5 --- docs/gluon-quartic-plan.md | 41 +++++++++++++++++++++++++++++----- madgraph/core/helas_objects.py | 27 ++++++++++++++++++++-- 2 files changed, 61 insertions(+), 7 deletions(-) diff --git a/docs/gluon-quartic-plan.md b/docs/gluon-quartic-plan.md index d376681c38..4872639c66 100644 --- a/docs/gluon-quartic-plan.md +++ b/docs/gluon-quartic-plan.md @@ -445,11 +445,42 @@ seven). It is not shipped, because it makes `g g > g g g g` come out **wrong in madmatrix** (2.43e-04 against 1.59e-04) while Fortran stays exact at N=2..5. -The generated code has no read before write, and a matrix element built -directly has no duplicate wavefunction listings — those appear only through -the madmatrix exporter path, which is also what forced the `allocated` guard -in step 8. So the reordering is exposing something latent on that side rather -than being wrong itself, but that has to be understood before it can go in. +Investigated, and the cause is now located even if not yet fixed. + +Ruled out, each by measurement rather than argument: + +* not the reordering itself — with the current sums switched off, the + reordered madmatrix is exact; +* not slot corruption — replaying the emission against the slot map gives no + read before write, no sum aliasing one of its own inputs, and `nwf` covers + every index used; +* not `coloramps.h` — the only difference there is the channel to iconfig map + (`nchannels` 160 against 220, since it is taken as the *largest diagram + number carrying a channel*, which the reordering moves), while `icolamp` is + identical and the plain matrix element reads neither; +* not the `merge_quartic_amplitudes=False` path — forcing the Fortran writer + into the same semantics, no amplitude folds and the merges left in the + JAMPs, is exact under the reordering; +* not the duplicate wavefunction listings on their own — suppressing the + second emission moves the wrong answer (2.36e-04) without fixing it. + +What it *is*, from replaying both generated files symbolically — every slot +carrying an expression tree, every amplitude reduced to one, compared as +multisets: + +| | amplitudes | differing under the reordering | +|---|---|---| +| standalone Fortran | 450 | **0** | +| madmatrix | 450 | **40** | + +**The folding is ordering sensitive in madmatrix and not in Fortran.** The +madmatrix matrix element carries 20 wavefunctions listed by two diagrams — +two objects for the same current, which a directly built matrix element does +not have — and `match_quartic_mothers` compares mothers by number, so which +copy an amplitude happens to hold decides which pairs get matched. The +committed order happens to give a correct folding; the reordering does not. + +So the duplicate wavefunctions are the thing to fix, not the order. Worth doing: at six gluons it would take the wavefunction store from 6600 B to 2700 B, *under* the 5100 B of the unoptimised code, with every current sum diff --git a/madgraph/core/helas_objects.py b/madgraph/core/helas_objects.py index 7943a2b6e5..fd6ec1f670 100755 --- a/madgraph/core/helas_objects.py +++ b/madgraph/core/helas_objects.py @@ -6421,13 +6421,29 @@ def match_quartic_mothers(source, target, unrollable, cubic_ids): @staticmethod def is_unrolled_pair(quartic, cubic, unrollable, cubic_ids): """True when the cubic current is the pair of vertices the quartic one - factorises into: same four lines coming in, same line going out.""" + factorises into: same four lines coming in, same line going out, and + the colour structure the quartic carries is the one which separates + the two lines the inner cubic vertex joins. + + That last condition is the one which is easy to forget. A quartic + vertex makes one current per colour structure, and all of them take + the same lines and make the same line, so the lines alone cannot tell + them apart -- only the pairing can, and it has to be read against + sorted_mothers, the order ALOHA receives the legs in.""" if quartic.get('interaction_id') not in unrollable or \ cubic.get('interaction_id') not in cubic_ids or \ quartic.get('number_external') != cubic.get('number_external'): return False + pairings = unrollable[quartic.get('interaction_id')][1] + if quartic.get('color_key') >= len(pairings): + return False + pairing = pairings[quartic.get('color_key')] + mothers = HelasMatrixElement.sorted_mothers(quartic) + outgoing = quartic.find_outgoing_number() - 1 + slots = [i for i in range(len(mothers) + 1) if i != outgoing] + wanted = sorted(mother.get('number') for mother in quartic.get('mothers')) for inner in cubic.get('mothers'): @@ -6437,7 +6453,14 @@ def is_unrolled_pair(quartic, cubic, unrollable, cubic_ids): if sorted([mother.get('number') for mother in inner.get('mothers')] + [other.get('number') for other in cubic.get('mothers') - if other is not inner]) == wanted: + if other is not inner]) != wanted: + continue + joined = set(mother.get('number') + for mother in inner.get('mothers')) + separated = frozenset(slots[i] for i, mother in enumerate(mothers) + if mother.get('number') in joined) + if frozenset(pairing[0]) == separated or \ + frozenset(pairing[1]) == separated: return True return False From 2c34b7c19cc3415c4996c4d7387891f604660300 Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 19:46:25 +0200 Subject: [PATCH 25/39] find why the reordering breaks madmatrix: an antisymmetric current merged by equality Root cause, and it is a latent MG5 bug rather than one of this optimisation. The reconstruction can build the same cubic current with its two mothers in either order, and sorted_mothers leaves them alone because for two identical gluons its key ties. VVV1P0_1 is antisymmetric under exchanging its two inputs -- measured, VVV1P0_1(a,b) + VVV1P0_1(b,a) = 0 exactly -- so the two objects are negatives of each other. HelasWavefunction.__eq__ compares mothers by sorted number and calls them equal, and export_cpp renumbers wavefunctions by that equality, so the two land on one slot inside a single matrix element and one of them silently carries the wrong sign. The Fortran writer never hits it because it does not renumber by equality. With the committed diagram order the collisions happen not to matter; the reordering moves them somewhere they do. Co-Authored-By: Claude Opus 5 --- docs/gluon-quartic-plan.md | 39 ++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/docs/gluon-quartic-plan.md b/docs/gluon-quartic-plan.md index 4872639c66..16a88d9b11 100644 --- a/docs/gluon-quartic-plan.md +++ b/docs/gluon-quartic-plan.md @@ -473,14 +473,37 @@ multisets: | standalone Fortran | 450 | **0** | | madmatrix | 450 | **40** | -**The folding is ordering sensitive in madmatrix and not in Fortran.** The -madmatrix matrix element carries 20 wavefunctions listed by two diagrams — -two objects for the same current, which a directly built matrix element does -not have — and `match_quartic_mothers` compares mothers by number, so which -copy an amplitude happens to hold decides which pairs get matched. The -committed order happens to give a correct folding; the reordering does not. - -So the duplicate wavefunctions are the thing to fix, not the order. +**The folding is ordering sensitive in madmatrix and not in Fortran**, and +running that down gives the root cause. It is a latent bug in MG5 itself, +which the reordering exposes rather than causes: + +1. The reconstruction can build the same cubic current with its two mothers + in either order — the colliding pairs are `interaction 3, colour_key 0, + mothers [7,3]` against `[3,7]`. `sorted_mothers` leaves them alone, + because for two identical gluons its key ties and the sort is stable. +2. **`VVV1P0_1` is antisymmetric under exchanging its two inputs.** Measured, + not read off the source: with a fixed pair of wavefunctions, + `VVV1P0_1(a,b) + VVV1P0_1(b,a) = 0` exactly. So the two objects are + *negatives* of each other and write out calls differing by a sign. +3. **`HelasWavefunction.__eq__` compares mothers by sorted number**, so it + calls them equal — "the number for this wavefunction, the pdg code, and + the interaction id are irrelevant". +4. `export_cpp.generate_process_files` renumbers wavefunctions by that + equality, to share them between matrix elements. The two therefore end up + on **one number and one slot inside a single matrix element**, and + whichever is written last wins — with the wrong sign for the other. + +The Fortran writer never hits it because it does not renumber by equality. +With the committed diagram order the collisions happen not to matter; the +reordering moves them somewhere they do. + +The fix is upstream of this optimisation: either `__eq__` compares mothers in +order rather than sorted (safe for every vertex whose particles differ, since +`sorted_mothers` then fixes the order anyway, but it changes the wavefunction +CSE everywhere and needs validating with the flag off), or the reconstruction +is made to produce only one of the two orders. Canonicalising the pair inside +`split_quartic_vertex` alone is *not* enough — the other copy can come from a +vertex the reconstruction did not build. Worth doing: at six gluons it would take the wavefunction store from 6600 B to 2700 B, *under* the 5100 B of the unoptimised code, with every current sum From d80a7a03a36b90d3636d1e792a5ed3a14fa63baf Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 20:01:26 +0200 Subject: [PATCH 26/39] table the memory and speed across the three states of the branch Flag off, the branch before this work (3b3ed9e85, amplitude merges only), and today. The generated code at the time the pull request was opened is byte-identical to today in both backends for N=2..5, the only code change since being the colour structure check, so those are one column. Records too that madmatrix had no usable numbers before this work: get_color_amplitudes dropped every merge source unconditionally while only the Fortran writer wrote the sums back, so any C++ output with the flag set lost 405 of its 510 amplitudes at six gluons. Co-Authored-By: Claude Opus 5 --- docs/gluon-quartic-plan.md | 45 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/docs/gluon-quartic-plan.md b/docs/gluon-quartic-plan.md index 16a88d9b11..9cbd7d8682 100644 --- a/docs/gluon-quartic-plan.md +++ b/docs/gluon-quartic-plan.md @@ -384,6 +384,51 @@ vertex is the whole amplitude). Five gluons loses on madmatrix, where the wavefunction store grows by half and there is no JAMP fold to pay for it. Six and seven gluons win on both, and the gain grows with the multiplicity. +**Where it came from.** Three states: the flag off (what an unoptimised build +gives), the branch as it stood before this work (`3b3ed9e85`, only the +amplitude merges of `fcd8218b6`), and the flag on today. The generated code at +the time the pull request was opened (`fefb1159b`) is **byte-identical** to +today's in both backends for N=2..5 -- the only code change since is the +colour-structure check in `is_unrolled_pair`, which provably moves nothing -- +so those two are one column. + +standalone Fortran, `slots / wavefunction calls + sums / amplitude calls`: + +| | flag off | before this work | at PR open = now | +|---|---|---|---| +| `g g > g g` | 5 / 7 / 6 | 5 / 7 / 6 | 5 / 7 / 6 | +| `g g > g g g` | 12 / 33 / 45 | 12 / 33 / 45 | **19 / 39+7 / 38** | +| `g g > g g g g` | 51 / 111 / 510 | 51 / 111 / 510 | **66 / 146+30 / 450** | +| `g g > 5 g` | 268 / 898 / 7245 | 268 / 898 / 7245 | **290 / 955+60 / 6813** | + +madmatrix, `slots / amplitude calls`: + +| | flag off | before this work | at PR open = now | +|---|---|---|---| +| `g g > g g` | 5 / 6 | *wrong* | 5 / 6 | +| `g g > g g g` | 12 / 45 | *wrong* | **19 / 38** | +| `g g > g g g g` | 51 / 510 | *wrong* | **86 / 450** | +| `g g > 5 g` | 268 / 7245 | *wrong* | **320 / 6813** | + +"wrong" is not a figure of speech: at `3b3ed9e85` `get_color_amplitudes` dropped +every merge source from the JAMPs unconditionally, and only the Fortran writer +wrote the sums putting them back, so with the flag set any C++ or python output +lost 405 of its 510 amplitudes at six gluons, silently. That is fixed here. + +Per-call time, standalone Fortran (lower is better) and madmatrix in evt/s +(higher is better): + +| | fortran off | fortran before | fortran now | madmatrix off | madmatrix now | +|---|---|---|---|---|---| +| `g g > g g` | 11.00 s | 11.28 s | 11.04 s | 875150 | 878724 | +| `g g > g g g` | 34.90 s | 33.98 s | 34.99 s | 72359 | 66757 | +| `g g > g g g g` | 47.35 s | 48.12 s | **45.61 s** | 2699 | **2784** | +| `g g > 5 g` | 43.05 s | 40.88 s | **39.98 s** | 41.75 | **43.33** | + +The "before" column was taken in its own batch and carries about 1% of drift +against the other two, which were measured together -- so compare off against +now, and read "before" only for the shape. + **Memory — the wavefunction store**, which is what the optimisation costs. `NWAVEFUNCS` in Fortran, `nwf` in madmatrix; bytes are 100 per wavefunction in Fortran (4 complex, 4 reals, one int) and 192 in madmatrix on sse4 in double From c5624c1ff6f1dc579ac00a2a4c7616c49c4d1fc5 Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 21:05:05 +0200 Subject: [PATCH 27/39] build the unrolled vertices with their legs in a canonical order, and reorder The wavefunction count went *up* under the flag, which it should not have. Measured at six gluons: 111 -> 146, and 20 of the 35 extra are the same current built with its two mothers in the opposite order. sorted_mothers leaves them alone, because for two identical gluons its key ties and the sort is stable, so they stay two objects -- and being negatives of each other (VVV1P0_1 is antisymmetric, measured: VVV1P0_1(a,b) + VVV1P0_1(b,a) = 0) they cannot be shared. Taking the legs of both unrolled vertices in a canonical order removes every one of them: wavefunctions of which order-flipped twins g g > g g g 33 -> 39 0 -> 0 g g > g g g g 111 -> 126 (was 146) 20 -> 0 g g > 5 g 898 -> 925 (was 955) 30 -> 0 That also removes the reason the last-discovery diagram order could not be used. Those twins are what HelasWavefunction.__eq__ calls equal while they differ by a sign, and export_cpp renumbers wavefunctions by that equality, so they landed on one slot inside one matrix element and one of them silently carried the wrong sign. With no twins left there is nothing to collide, and the order goes in: each diagram is placed at its last discovery, which puts it after every seed which can reach it and therefore after every quartic current which can be summed into it. All the sums survive. NWAVEFUNCS off before now g g > g g g 12 19 19 g g > g g g g 51 66 78 g g > 5 g 268 290 259 per call / evt/s off before now fortran g g > g g g g 47.77 s 45.61 s 45.25 s +5.3% fortran g g > 5 g 42.19 s 39.98 s 40.10 s +4.9% madmatrix g g > g g g 74229 66757 67566 -9.0% madmatrix g g > g g g g 2651 2784 2880 +8.6% |M|^2 stays exact: bit-identical at four gluons, 1e-16 at five, 1e-14 at six and seven, in both backends. With the flag off matrix.f and CPPProcess.cc are byte-identical to before. Co-Authored-By: Claude Opus 5 --- madgraph/core/diagram_generation.py | 30 ++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/madgraph/core/diagram_generation.py b/madgraph/core/diagram_generation.py index d0eafa14ea..5e12d77a16 100755 --- a/madgraph/core/diagram_generation.py +++ b/madgraph/core/diagram_generation.py @@ -621,7 +621,8 @@ def split_quartic_vertex(vertex, is_last, pairing, cubic_id, model): # the new internal line first, second = second, first - combined = [ordered[i] for i in first] + combined = sorted([ordered[i] for i in first], + key=lambda leg: leg.get('number')) new_leg = base_objects.Leg({ 'id': combined[0].get('id'), 'number': min(leg.get('number') for leg in combined), @@ -632,11 +633,13 @@ def split_quartic_vertex(vertex, is_last, pairing, cubic_id, model): 'legs': base_objects.LegList(combined + [new_leg]), 'id': cubic_id}) if is_last: - rest = [ordered[i] for i in second] + [new_leg] + rest = sorted([ordered[i] for i in second] + [new_leg], + key=lambda leg: leg.get('number')) else: # the outgoing leg has to stay last - rest = [ordered[i] for i in second if i != out_position] + \ - [new_leg, ordered[out_position]] + rest = sorted([ordered[i] for i in second if i != out_position] + + [new_leg], key=lambda leg: leg.get('number')) + \ + [ordered[out_position]] second_vx = base_objects.Vertex({'legs': base_objects.LegList(rest), 'id': cubic_id}) @@ -1410,6 +1413,18 @@ def canonical_tag(diagram): res = base_objects.DiagramList() seen = set() + tag_of = [] + last_seen = {} + clock = [0] + + def touch(tag): + # A diagram is placed at its *last* discovery, so that it lands + # after every seed which can reach it -- and so after every + # quartic current which can be summed into it. Seeing it again + # only moves it later, it is never generated twice. + clock[0] += 1 + last_seen[tag] = clock[0] + self.quartic_unroll_tags = {} todo = [] for diagram in seed: @@ -1423,7 +1438,9 @@ def canonical_tag(diagram): diagram = self.create_diagram(vertices) tag = canonical_tag(diagram) seen.add(tag) + touch(tag) res.append(diagram) + tag_of.append(tag) todo.append((diagram, tag)) # Unrolling is confluent, so taking the diagrams it produces through @@ -1452,16 +1469,19 @@ def canonical_tag(diagram): continue unrolled = self.unrolled_diagram(diagram, choice, unrollable) tag = canonical_tag(unrolled) + touch(tag) if tag not in seen: seen.add(tag) res.append(unrolled) + tag_of.append(tag) todo.append((unrolled, tag)) if len(choice) == len(positions): chain = tuple(choice.get(i, 0) for i in range(len(vertices))) self.quartic_unroll_tags[(own_tag, chain)] = tag - return res + order = sorted(range(len(res)), key=lambda i: (last_seen[tag_of[i]], i)) + return base_objects.DiagramList([res[i] for i in order]) def get_quartic_unroll_links(self, diaglist=None): """Return {(diagram index, colour chain): target index} recorded while From 473d04f4824f43c8f3bf5f510311b94988d44146 Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 21:06:57 +0200 Subject: [PATCH 28/39] update the tables for the canonical leg order and the reordering Co-Authored-By: Claude Opus 5 --- docs/gluon-quartic-plan.md | 142 ++++++++++++++----------------------- 1 file changed, 52 insertions(+), 90 deletions(-) diff --git a/docs/gluon-quartic-plan.md b/docs/gluon-quartic-plan.md index 9cbd7d8682..92d0546396 100644 --- a/docs/gluon-quartic-plan.md +++ b/docs/gluon-quartic-plan.md @@ -386,29 +386,25 @@ and seven gluons win on both, and the gain grows with the multiplicity. **Where it came from.** Three states: the flag off (what an unoptimised build gives), the branch as it stood before this work (`3b3ed9e85`, only the -amplitude merges of `fcd8218b6`), and the flag on today. The generated code at -the time the pull request was opened (`fefb1159b`) is **byte-identical** to -today's in both backends for N=2..5 -- the only code change since is the -colour-structure check in `is_unrolled_pair`, which provably moves nothing -- -so those two are one column. +amplitude merges of `fcd8218b6`), and the flag on today. standalone Fortran, `slots / wavefunction calls + sums / amplitude calls`: -| | flag off | before this work | at PR open = now | -|---|---|---|---| -| `g g > g g` | 5 / 7 / 6 | 5 / 7 / 6 | 5 / 7 / 6 | -| `g g > g g g` | 12 / 33 / 45 | 12 / 33 / 45 | **19 / 39+7 / 38** | -| `g g > g g g g` | 51 / 111 / 510 | 51 / 111 / 510 | **66 / 146+30 / 450** | -| `g g > 5 g` | 268 / 898 / 7245 | 268 / 898 / 7245 | **290 / 955+60 / 6813** | +| | flag off | before this work | at PR open | now | +|---|---|---|---|---| +| `g g > g g` | 5 / 7 / 6 | 5 / 7 / 6 | 5 / 7 / 6 | 5 / 7 / 6 | +| `g g > g g g` | 12 / 33 / 45 | 12 / 33 / 45 | 19 / 39+7 / 38 | 19 / 39+7 / 38 | +| `g g > g g g g` | 51 / 111 / 510 | 51 / 111 / 510 | 66 / 146+30 / 450 | **78 / 126+30 / 450** | +| `g g > 5 g` | 268 / 898 / 7245 | 268 / 898 / 7245 | 290 / 955+60 / 6813 | **259 / 925+60 / 6813** | madmatrix, `slots / amplitude calls`: -| | flag off | before this work | at PR open = now | -|---|---|---|---| -| `g g > g g` | 5 / 6 | *wrong* | 5 / 6 | -| `g g > g g g` | 12 / 45 | *wrong* | **19 / 38** | -| `g g > g g g g` | 51 / 510 | *wrong* | **86 / 450** | -| `g g > 5 g` | 268 / 7245 | *wrong* | **320 / 6813** | +| | flag off | before this work | at PR open | now | +|---|---|---|---|---| +| `g g > g g` | 5 / 6 | *wrong* | 5 / 6 | 5 / 6 | +| `g g > g g g` | 12 / 45 | *wrong* | 19 / 38 | 19 / 38 | +| `g g > g g g g` | 51 / 510 | *wrong* | 86 / 450 | **78 / 450** | +| `g g > 5 g` | 268 / 7245 | *wrong* | 320 / 6813 | **259 / 6813** | "wrong" is not a figure of speech: at `3b3ed9e85` `get_color_amplitudes` dropped every merge source from the JAMPs unconditionally, and only the Fortran writer @@ -418,16 +414,15 @@ lost 405 of its 510 amplitudes at six gluons, silently. That is fixed here. Per-call time, standalone Fortran (lower is better) and madmatrix in evt/s (higher is better): -| | fortran off | fortran before | fortran now | madmatrix off | madmatrix now | -|---|---|---|---|---|---| -| `g g > g g` | 11.00 s | 11.28 s | 11.04 s | 875150 | 878724 | -| `g g > g g g` | 34.90 s | 33.98 s | 34.99 s | 72359 | 66757 | -| `g g > g g g g` | 47.35 s | 48.12 s | **45.61 s** | 2699 | **2784** | -| `g g > 5 g` | 43.05 s | 40.88 s | **39.98 s** | 41.75 | **43.33** | +| | off | before | at PR open | now | +|---|---|---|---|---| +| fortran `g g > g g g g` | 47.77 s | 48.12 s | 45.61 s | **45.25 s (+5.3%)** | +| fortran `g g > 5 g` | 42.19 s | 40.88 s | 39.98 s | **40.10 s (+4.9%)** | +| madmatrix `g g > g g g` | 74229 | *wrong* | 66757 | 67566 (-9.0%) | +| madmatrix `g g > g g g g` | 2651 | *wrong* | 2784 | **2880 (+8.6%)** | -The "before" column was taken in its own batch and carries about 1% of drift -against the other two, which were measured together -- so compare off against -now, and read "before" only for the shape. +Timings taken in batches, and there is about 1% of drift between batches, so +each column should be read against the `off` measured with it. **Memory — the wavefunction store**, which is what the optimisation costs. `NWAVEFUNCS` in Fortran, `nwf` in madmatrix; bytes are 100 per wavefunction in @@ -488,71 +483,38 @@ seed which can reach it — and takes both: all the sums, and a slot count *below* the flag off baseline (27 against 51 at six gluons, 219 against 268 at seven). -It is not shipped, because it makes `g g > g g g g` come out **wrong in -madmatrix** (2.43e-04 against 1.59e-04) while Fortran stays exact at N=2..5. -Investigated, and the cause is now located even if not yet fixed. - -Ruled out, each by measurement rather than argument: - -* not the reordering itself — with the current sums switched off, the - reordered madmatrix is exact; -* not slot corruption — replaying the emission against the slot map gives no - read before write, no sum aliasing one of its own inputs, and `nwf` covers - every index used; -* not `coloramps.h` — the only difference there is the channel to iconfig map - (`nchannels` 160 against 220, since it is taken as the *largest diagram - number carrying a channel*, which the reordering moves), while `icolamp` is - identical and the plain matrix element reads neither; -* not the `merge_quartic_amplitudes=False` path — forcing the Fortran writer - into the same semantics, no amplitude folds and the merges left in the - JAMPs, is exact under the reordering; -* not the duplicate wavefunction listings on their own — suppressing the - second emission moves the wrong answer (2.36e-04) without fixing it. - -What it *is*, from replaying both generated files symbolically — every slot -carrying an expression tree, every amplitude reduced to one, compared as -multisets: - -| | amplitudes | differing under the reordering | +**Shipped, once the reason it broke madmatrix was found.** The blocker was not +the order at all: + +1. The reconstruction could build the same cubic current with its two mothers + in either order. `sorted_mothers` leaves them alone, because for two + identical gluons its key ties and the sort is stable, so they stay two + objects. +2. **`VVV1P0_1` is antisymmetric under exchanging its two inputs.** Measured: + `VVV1P0_1(a,b) + VVV1P0_1(b,a) = 0` exactly. So the two are *negatives* of + each other and write out calls differing by a sign. +3. **`HelasWavefunction.__eq__` compares mothers by sorted number** and calls + them equal -- "the number for this wavefunction, the pdg code, and the + interaction id are irrelevant". +4. `export_cpp` renumbers wavefunctions by that equality, so the two landed on + one number and one slot inside a single matrix element and one of them + silently carried the wrong sign. The Fortran writer never hits it because + it does not renumber by equality. + +Taking the legs of both unrolled vertices in a canonical order removes every +such pair -- 20 of the 35 extra wavefunctions at six gluons, 30 of 57 at seven +-- so there is nothing left to collide, and the order goes in. + +| | wavefunctions | order-flipped twins | |---|---|---| -| standalone Fortran | 450 | **0** | -| madmatrix | 450 | **40** | - -**The folding is ordering sensitive in madmatrix and not in Fortran**, and -running that down gives the root cause. It is a latent bug in MG5 itself, -which the reordering exposes rather than causes: - -1. The reconstruction can build the same cubic current with its two mothers - in either order — the colliding pairs are `interaction 3, colour_key 0, - mothers [7,3]` against `[3,7]`. `sorted_mothers` leaves them alone, - because for two identical gluons its key ties and the sort is stable. -2. **`VVV1P0_1` is antisymmetric under exchanging its two inputs.** Measured, - not read off the source: with a fixed pair of wavefunctions, - `VVV1P0_1(a,b) + VVV1P0_1(b,a) = 0` exactly. So the two objects are - *negatives* of each other and write out calls differing by a sign. -3. **`HelasWavefunction.__eq__` compares mothers by sorted number**, so it - calls them equal — "the number for this wavefunction, the pdg code, and - the interaction id are irrelevant". -4. `export_cpp.generate_process_files` renumbers wavefunctions by that - equality, to share them between matrix elements. The two therefore end up - on **one number and one slot inside a single matrix element**, and - whichever is written last wins — with the wrong sign for the other. - -The Fortran writer never hits it because it does not renumber by equality. -With the committed diagram order the collisions happen not to matter; the -reordering moves them somewhere they do. - -The fix is upstream of this optimisation: either `__eq__` compares mothers in -order rather than sorted (safe for every vertex whose particles differ, since -`sorted_mothers` then fixes the order anyway, but it changes the wavefunction -CSE everywhere and needs validating with the flag off), or the reconstruction -is made to produce only one of the two orders. Canonicalising the pair inside -`split_quartic_vertex` alone is *not* enough — the other copy can come from a -vertex the reconstruction did not build. - -Worth doing: at six gluons it would take the wavefunction store from 6600 B to -2700 B, *under* the 5100 B of the unoptimised code, with every current sum -kept. +| `g g > g g g` | 33 -> 39 | 0 | +| `g g > g g g g` | 111 -> 126 (was 146) | 20 -> 0 | +| `g g > 5 g` | 898 -> 925 (was 955) | 30 -> 0 | + +Placing each diagram at its last discovery then puts it after every seed which +can reach it, hence after every quartic current summable into it, so all the +sums survive. `NWAVEFUNCS` at seven gluons ends up **below** the unoptimised +build: 259 against 268. ## Where to go next From 4be98718749ab65151f4b155a24be186749f6064 Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 21:27:54 +0200 Subject: [PATCH 29/39] search the diagram order for the slot count, and keep the simple one Six orders measured. Reordering never changes which currents exist, only how long each is alive, so the wavefunction count is the same throughout. The shipped last-discovery order gives 19/78/259 and nothing beats it while keeping the sums: reversing it gives 12/54/199, far the best, and loses every sum, because it puts each target ahead of the quartic currents feeding it. A register-pressure greedy under the unrolling precedence buys 19 -> 18 and 78 -> 76 and nothing at seven gluons, for an O(n^2) pass taking generation from 0.88 s to 3.24 s there and minutes at eight gluons. Not kept. Co-Authored-By: Claude Opus 5 --- docs/gluon-quartic-plan.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/docs/gluon-quartic-plan.md b/docs/gluon-quartic-plan.md index 92d0546396..2a2c903849 100644 --- a/docs/gluon-quartic-plan.md +++ b/docs/gluon-quartic-plan.md @@ -516,6 +516,36 @@ can reach it, hence after every quartic current summable into it, so all the sums survive. `NWAVEFUNCS` at seven gluons ends up **below** the unoptimised build: 259 against 268. +## The slot ordering, searched + +Once the twins are gone the slot count is the same in both backends (78 and +259 at six and seven gluons), so the order is one shared problem rather than a +per-backend one. Six orders were built and measured. The wavefunction count is +the same in all of them -- reordering the diagrams never changes *which* +currents exist, only how long each stays alive: + +| order | `g g > g g g` | `g g > g g g g` | `g g > 5 g` | sums kept | +|---|---|---|---|---| +| last discovery (shipped) | 19 | 78 | 259 | yes | +| first discovery | 19 | 81 | 314 | yes | +| by quartic count | 19 | 81 | 314 | yes | +| by quartic count, then last | 19 | 81 | 259 | yes | +| last discovery, then quartic count | 19 | 78 | 259 | yes | +| **reversed last discovery** | **12** | **54** | **199** | **no -- all lost** | + +The last row is the interesting one: it is far the best on slots and useless, +because reversing puts each target ahead of the quartic currents which feed +it, so no sum can be built. That is the trade in one line -- the constraint +that makes the sums possible is what costs the slots. + +A proper register-pressure greedy was also written: order the diagrams under +the precedence "everything which unrolls to a diagram comes before it", and at +each step take the one leaving fewest currents alive. It buys 19 -> 18 and +78 -> 76 and **nothing at all** at seven gluons, for an O(n^2) pass which +takes generation from 0.88 s to 3.24 s at seven gluons and would cost minutes +at eight. Not worth it; the shipped order is within a couple of slots of what +the search finds. + ## Where to go next **Give madmatrix the amplitude sums too.** It is the only backend without From 5e5d7b380e4e71410ff99073541715923e234949 Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 22:26:21 +0200 Subject: [PATCH 30/39] turn the four gluon switch into a set option, and add the slots mode MG_MERGE_QUARTIC becomes "set merge_quartic_vertices ", taking False (the default), speed or slots. True is accepted as a synonym for speed. The interface pushes it onto madgraph.merge_quartic_vertices, which is what the generation and the exporters read; do_add syncs it as well, since the option can also arrive from mg5_configuration.txt where the setter is not called. It cannot be an output option. The diagram order is fixed while the diagrams are generated, so by output time it is already too late. The new mode is the one the gpu question asks for. The wavefunction store is a stack frame on cpu but is per thread on gpu -- about 24 kB a thread at seven gluons -- so which way the trade goes depends on the hardware: g g > 5 g amplitude calls slots per thread off 7245 268 25.1 kB speed 6813 259 24.3 kB slots 7245 199 18.7 kB 6% more arithmetic for 23% less memory. 'slots' reverses the diagram order, which is far the best on register pressure and puts each target ahead of the quartic currents feeding it, so the current sums cannot be built -- the amplitude merges, and the JAMP block they shrink, are kept. Which one a gpu wants has not been measured: there is no device here. |M|^2 checked for all three values at five and six gluons in both backends, and with no 'set' at all the generated matrix.f is byte-identical to the unoptimised one. Co-Authored-By: Claude Opus 5 --- docs/gluon-quartic-plan.md | 33 +++++++++++++-- madgraph/__init__.py | 13 ++++-- madgraph/core/diagram_generation.py | 7 ++++ madgraph/core/helas_objects.py | 5 ++- madgraph/interface/madgraph_interface.py | 53 ++++++++++++++++++++++-- madgraph/interface/master_interface.py | 3 ++ madmatrix/model_handling.py | 2 +- 7 files changed, 104 insertions(+), 12 deletions(-) diff --git a/docs/gluon-quartic-plan.md b/docs/gluon-quartic-plan.md index 2a2c903849..8d363c4578 100644 --- a/docs/gluon-quartic-plan.md +++ b/docs/gluon-quartic-plan.md @@ -1,7 +1,32 @@ # Pure-gluon amplitude optimisation — plan Branch `claude/gluon-amplitude-optimization-8706f5`. Everything is behind -`MG_MERGE_QUARTIC` (off by default), so nothing changes until it is set. +`set merge_quartic_vertices` (off by default), so nothing changes until it is +set. It takes three values: + +| | | +|---|---| +| `False` | off, the default | +| `speed` | the current sums, and the diagram order which allows them | +| `slots` | the order which keeps fewest currents alive; no current sums | + +It has to be a `set` option and not an `output` one, because the diagram order +is fixed while the diagrams are generated -- by `output` time it is already +too late. The interface pushes it onto `madgraph.merge_quartic_vertices`, +which is what the generation and the exporters read. + +**speed against slots.** The wavefunction store is a stack frame on cpu and is +per thread on gpu, where at seven gluons it is about 24 kB a thread and caps +occupancy. So the trade goes opposite ways: + +| `g g > 5 g` | amplitude calls | slots | per thread | +|---|---|---|---| +| off | 7245 | 268 | 25.1 kB | +| `speed` | 6813 | 259 | 24.3 kB | +| `slots` | 7245 | **199** | **18.7 kB** | + +6% more arithmetic for 23% less memory. Measured on cpu `speed` wins; which +one a gpu wants has *not* been measured -- there is no device here. ## Goal @@ -300,7 +325,7 @@ emits them exactly as the Fortran one does. **The colour amplitudes had to be sorted out first, and that was a live bug.** `get_color_amplitudes` dropped every merge source from the JAMPs on the assumption that the caller writes the amplitude sums to put them back. Only -the Fortran writer does, so C++ and python output with `MG_MERGE_QUARTIC` set +the Fortran writer does, so C++ and python output with the flag set was quietly losing four fifths of the amplitude. It now takes `merge_quartic_amplitudes`; a backend which writes no sums keeps those amplitudes in the JAMPs, where their own colour coefficients give the @@ -363,7 +388,7 @@ bottleneck. The madevent run is unchanged, same cross section and error. ## Results -Everything below is `g g > N g` with `MG_MERGE_QUARTIC` off against on, on the +Everything below is `g g > N g` with the flag off against `speed`, on the same machine. Standalone Fortran is the shipped `check` driver looping `SMATRIX`; madmatrix is `check_sa.exe perf` built `FPTYPE=d` on `cppsse4` (the default mixed precision build rounds the two to the same value and would @@ -638,7 +663,7 @@ graph (225 instead of 105 at six gluons). ## Measuring -Generation: `MG_MERGE_QUARTIC=1 ./bin/mg5_aMC` then `generate g g > g g g g`. +Generation: `set merge_quartic_vertices speed` then `generate g g > g g g g`. Compare `matrix.f` against a run without the variable. Tests: `./tests/test_manager.py -p U test_diagram_generation test_color_amp test_helas_objects test_base_objects` (199, must stay green with the flag off). diff --git a/madgraph/__init__.py b/madgraph/__init__.py index e4c7ffc3e9..5bbdbb358b 100755 --- a/madgraph/__init__.py +++ b/madgraph/__init__.py @@ -63,7 +63,14 @@ class aMCatNLOError(MadGraph5Error): # Sum the quartic gluon contributions into the cubic amplitude carrying the # same colour factor, see HelasMatrixElement.get_quartic_amplitude_merges. -# Off by default while the optimisation is being benchmarked. -merge_quartic_vertices = os.environ.get('MG_MERGE_QUARTIC', '') not in \ - ('', '0', 'False') +# Set through the interface, "set merge_quartic_vertices ", and read +# here because it is wanted while the diagrams are generated, long before any +# exporter exists. False, or one of: +# 'speed' -- the current sums, and the diagram order which allows them. Wins +# on cpu, where the amplitude calls dominate. +# 'slots' -- no current sums, and the order which keeps fewest currents +# alive. Trades 6% more amplitude calls for 23% fewer +# wavefunction slots at seven gluons, which is the trade a gpu +# wants when occupancy is the limit. +merge_quartic_vertices = False diff --git a/madgraph/core/diagram_generation.py b/madgraph/core/diagram_generation.py index 5e12d77a16..d9f5a0fc11 100755 --- a/madgraph/core/diagram_generation.py +++ b/madgraph/core/diagram_generation.py @@ -1481,6 +1481,13 @@ def touch(tag): self.quartic_unroll_tags[(own_tag, chain)] = tag order = sorted(range(len(res)), key=lambda i: (last_seen[tag_of[i]], i)) + if madgraph.merge_quartic_vertices == 'slots': + # Reversed, each diagram lands at its *first* discovery instead. + # That keeps far fewer currents alive -- 199 slots against 259 at + # seven gluons -- at the price of the current sums, since a target + # then comes before the quartic currents which feed it. The trade + # a gpu wants, where the wavefunction store is per thread. + order.reverse() return base_objects.DiagramList([res[i] for i in order]) def get_quartic_unroll_links(self, diaglist=None): diff --git a/madgraph/core/helas_objects.py b/madgraph/core/helas_objects.py index fd6ec1f670..4d975579eb 100755 --- a/madgraph/core/helas_objects.py +++ b/madgraph/core/helas_objects.py @@ -6297,7 +6297,10 @@ def compute_quartic_current_sums(self): """Work out the current sums, see get_quartic_current_sums.""" merges = self.get_quartic_amplitude_merges() - if not merges: + if not merges or madgraph.merge_quartic_vertices == 'slots': + # 'slots' orders the diagrams for the smallest wavefunction store + # instead, which puts a target ahead of the quartic currents + # feeding it, so no sum can be built return [], {}, set() model = self.get('processes')[0].get('model') diff --git a/madgraph/interface/madgraph_interface.py b/madgraph/interface/madgraph_interface.py index d7e1ef7fd0..647b38ef22 100755 --- a/madgraph/interface/madgraph_interface.py +++ b/madgraph/interface/madgraph_interface.py @@ -3155,7 +3155,8 @@ class MadGraphCmd(HelpToCmd, CheckValidForCmd, CompleteForCmd, CmdExtended): 'max_t_for_channel', 'zerowidth_tchannel', 'default_unset_couplings', - 'nlo_mixed_expansion' + 'nlo_mixed_expansion', + 'merge_quartic_vertices' ] _valid_nlo_modes = ['all','real','virt','sqrvirt','tree','noborn','LOonly', 'only'] _valid_sqso_types = ['==','<=','=','>'] @@ -3238,7 +3239,8 @@ class MadGraphCmd(HelpToCmd, CheckValidForCmd, CompleteForCmd, CmdExtended): 'max_t_for_channel': 99, # means no restrictions 'zerowidth_tchannel': True, 'nlo_mixed_expansion':True, - 'apply_flavor_grouping': True + 'apply_flavor_grouping': True, + 'merge_quartic_vertices': False } options_madevent = {'automatic_html_opening':True, @@ -3361,7 +3363,14 @@ def do_add(self, line): existing amplitudes or merge two model """ - + + # The four gluon merging is wanted while the diagrams are generated, + # which is below the interface, so it travels on the module. Synced + # here rather than only in the setter, since the option can also + # arrive from mg5_configuration.txt. + madgraph.merge_quartic_vertices = \ + self.options.get('merge_quartic_vertices', False) + args = self.split_arg(line) @@ -9146,6 +9155,44 @@ def set2_zerowidth_tchannel(self, args, log=True): self.check_set(args) self.options[args[0]] = banner_module.ConfigFile.format_variable(args[1], bool, args[0]) + def help_set2_merge_quartic_vertices(self): + logger.info("merge_quartic_vertices ",'$MG:color:GREEN') + logger.info(" > (default: False) [pure gluon amplitudes]") + logger.info(" > Sum each four gluon contribution into the cubic") + logger.info(" > amplitude carrying the same colour factor.") + logger.info(" > False : off") + logger.info(" > speed : fewest amplitude calls (best on cpu)") + logger.info(" > slots : smallest wavefunction store (for gpu, where") + logger.info(" > that store is per thread); costs the sums") + + def set2_merge_quartic_vertices(self, args, log=True): + """Sum the four gluon contributions into the cubic amplitude carrying + the same colour factor. + + Read while the diagrams are generated, so it has to be set before + 'generate' -- an output time option would come too late, the diagram + order is already fixed by then. + + Example: set merge_quartic_vertices speed + """ + args = ['merge_quartic_vertices'] + args + self.check_set(args) + value = args[1].lower() + if value in ('slots', 'speed'): + pass + elif value in ('false', '0', 'none', 'off'): + value = False + elif value in ('true', '1', 'on'): + value = 'speed' + else: + raise self.InvalidCmd( + "merge_quartic_vertices takes False, speed or slots," + " not '%s'" % args[1]) + self.options[args[0]] = value + madgraph.merge_quartic_vertices = value + if log: + logger.info('set merge_quartic_vertices to %s' % value) + def set2_store_rwgt_info(self,args, log=True): """Set whether the code should generate systematics information in the output LHE file at NLO Default is set to False. diff --git a/madgraph/interface/master_interface.py b/madgraph/interface/master_interface.py index b18de52528..0626731a10 100755 --- a/madgraph/interface/master_interface.py +++ b/madgraph/interface/master_interface.py @@ -612,6 +612,9 @@ def help_set2_include_lepton_initiated_processes(self, *args, **opts): def help_set2_loop_color_flows(self, *args, **opts): return self.cmd.help_set2_loop_color_flows(self, *args, **opts) + def help_set2_merge_quartic_vertices(self, *args, **opts): + return self.cmd.help_set2_merge_quartic_vertices(self, *args, **opts) + def help_set2_loop_optimized_output(self, *args, **opts): return self.cmd.help_set2_loop_optimized_output(self, *args, **opts) diff --git a/madmatrix/model_handling.py b/madmatrix/model_handling.py index 6f943285d8..7c029454ec 100644 --- a/madmatrix/model_handling.py +++ b/madmatrix/model_handling.py @@ -2532,7 +2532,7 @@ def _guard_open(group_mask): # Emit the opening of an `if` guard for a non-full grouped mask. return 'if( ( 0x%xULL >> iflavor ) & 0x1ULL ) {' % group_mask - # OM - the four gluon optimisation (MG_MERGE_QUARTIC). A quartic + # OM - the four gluon optimisation (set merge_quartic_vertices). A quartic # current and the cubic current carrying the same colour factor are # summed into a third one, which the amplitude reads instead, so that # one call gets both contributions and the quartic amplitude is never From 7f50f031bc8cad8fb76e6de54e8d6bf84828e29a Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 23:30:51 +0200 Subject: [PATCH 31/39] let each output pick the diagram order, from the me exporter merge_quartic_vertices gains 'auto': generate in the 'speed' order and let apply_quartic_diagram_order reverse it at output time, when the backend about to be handed the matrix elements is known. Only possible because the two modes differ in nothing but the order, and 'slots' is 'speed' reversed. The choice is read off the *matrix element* exporter rather than the output format. "output madevent --me_exporter=" hands one _curr_matrix_elements to both exporters in a single export_processes call, so its two backends cannot carry different orders -- and that is the cudacpp production path, the one case the option exists for. Keying on the format would hand it the cpu order; keying on the me exporter gives it 'slots', NWAVEFUNCS=54 rather than 78 at six gluons. Two pre-existing behaviours had to be worked around, neither of them specific to this option: - an export mutates the diagrams it is given, 345 of 757 vertex leg records on g g > g g g g, and reversing mutated diagrams gives an equivalent but differently numbered result. So the reordering starts from a copy taken before the first export. deepcopy of the amplitudes is not available -- it drags the model along and trips the array.array assert in color_algebra.create_copy -- but the diagrams alone copy cleanly, 0.011 s at seven gluons. - an export also drops the marks saying the diagrams came from a seed, so whether an amplitude may be reordered is read before the first export rather than at the output which wants to reorder it. Byte-identical checks: 'auto' + standalone reproduces a native 'speed' generation, 'auto' + standalone_mg7 a native 'slots' one, "output madevent --me_exporter=standalone_mg7" a native 'slots' madevent, and a session going standalone -> standalone_mg7 -> standalone reproduces its first output for the third. Processes the seed rule never applied to are untouched. 916 unit tests, three of them new, same two pre-existing failures. Co-Authored-By: Claude Opus 5 --- docs/gluon-quartic-plan.md | 50 ++++++++++- madgraph/__init__.py | 4 + madgraph/interface/madgraph_interface.py | 89 +++++++++++++++++-- .../core/test_diagram_generation.py | 50 +++++++++++ 4 files changed, 186 insertions(+), 7 deletions(-) diff --git a/docs/gluon-quartic-plan.md b/docs/gluon-quartic-plan.md index 8d363c4578..ac896b3208 100644 --- a/docs/gluon-quartic-plan.md +++ b/docs/gluon-quartic-plan.md @@ -2,19 +2,28 @@ Branch `claude/gluon-amplitude-optimization-8706f5`. Everything is behind `set merge_quartic_vertices` (off by default), so nothing changes until it is -set. It takes three values: +set. It takes four values: | | | |---|---| | `False` | off, the default | | `speed` | the current sums, and the diagram order which allows them | | `slots` | the order which keeps fewest currents alive; no current sums | +| `auto` | `slots` when the matrix elements go to a gpu backend, `speed` otherwise, decided per output | It has to be a `set` option and not an `output` one, because the diagram order is fixed while the diagrams are generated -- by `output` time it is already too late. The interface pushes it onto `madgraph.merge_quartic_vertices`, which is what the generation and the exporters read. +`auto` is the exception, and only because `slots` is the `speed` order +reversed: it generates the `speed` order and +`MadGraphCmd.apply_quartic_diagram_order` reverses it at `output` time, once +the backend about to be handed the matrix elements is known. The choice is +made from the *matrix element* exporter rather than the output format, so +`output madevent --me_exporter=` -- one output feeding two +backends off a single `_curr_matrix_elements` -- follows the gpu. + **speed against slots.** The wavefunction store is a stack frame on cpu and is per thread on gpu, where at seven gluons it is about 24 kB a thread and caps occupancy. So the trade goes opposite ways: @@ -571,6 +580,45 @@ takes generation from 0.88 s to 3.24 s at seven gluons and would cost minutes at eight. Not worth it; the shipped order is within a couple of slots of what the search finds. +## The backend-chosen order (`auto`) + +`speed` suits a cpu and `slots` suits a gpu, but one generation can feed both, +so `auto` defers the choice to `output`. It works only because the two modes +differ in nothing but the diagram order, and `slots` is `speed` reversed -- +verified byte for byte: generating in the `speed` order and reversing at +output time reproduces a native `slots` generation exactly, in both backends, +and a session going standalone -> standalone_mg7 -> standalone reproduces its +first output for the third. + +**The choice comes from the matrix element exporter, not the output format.** +`output madevent --me_exporter=` hands one +`self._curr_matrix_elements` to both exporters in a single `export_processes` +call, so the fortran driver and the gpu matrix elements *cannot* carry +different orders. Keying on the format would give that output the cpu order, +which is the one case the whole thing exists for; keying on the me exporter +gives it `slots` (measured: `NWAVEFUNCS=54` rather than 78 at six gluons). + +Two things had to be worked around, both pre-existing and neither specific to +this option: + +* **An export mutates the diagrams it is given** -- 345 of 757 vertex leg + records change on `g g > g g g g`. Reversing mutated diagrams gives an + equivalent but differently numbered result, so `apply_quartic_diagram_order` + reverses a copy taken before the first export. `copy.deepcopy` of the + *amplitudes* is not an option: it drags the model along and trips + `assert type(col_obj) != array.array` in `color_algebra.create_copy`. The + diagrams alone copy cleanly and cost 0.011 s at seven gluons. +* **An export also drops the marks saying the diagrams came from a seed** -- + after it, `seed_forbidden_cubic_ids` is empty and `quartic_unroll_tags` has + 0 entries instead of 405. So whether an amplitude may be reordered has to be + read before the first export, not at the output which wants to reorder. + +Two dead ends, both measured: reversing the `HelasMatrixElement` diagrams +instead of the amplitude's trips the lifetime assert in +`reuse_outdated_wavefunctions`, since a wavefunction number has to be first +seen in emission order; and restoring only `from_group` on the base diagrams +is not enough to undo an export. + ## Where to go next **Give madmatrix the amplitude sums too.** It is the only backend without diff --git a/madgraph/__init__.py b/madgraph/__init__.py index 5bbdbb358b..88155dbbb5 100755 --- a/madgraph/__init__.py +++ b/madgraph/__init__.py @@ -72,5 +72,9 @@ class aMCatNLOError(MadGraph5Error): # alive. Trades 6% more amplitude calls for 23% fewer # wavefunction slots at seven gluons, which is the trade a gpu # wants when occupancy is the limit. +# 'auto' -- generate as for 'speed', and let each output pick: 'slots' when +# the matrix elements go to a gpu backend, 'speed' otherwise. The +# interface resolves it to one of the two above before anything +# reads it again, so only the generation ever sees 'auto'. merge_quartic_vertices = False diff --git a/madgraph/interface/madgraph_interface.py b/madgraph/interface/madgraph_interface.py index 647b38ef22..79fc665895 100755 --- a/madgraph/interface/madgraph_interface.py +++ b/madgraph/interface/madgraph_interface.py @@ -3370,6 +3370,10 @@ def do_add(self, line): # arrive from mg5_configuration.txt. madgraph.merge_quartic_vertices = \ self.options.get('merge_quartic_vertices', False) + # an added process arrives in the generated order whatever an earlier + # output reordered, so the two have to be brought back together -- + # a value matching neither makes the next output redo all of them + self._quartic_order = 'mixed' args = self.split_arg(line) @@ -5016,6 +5020,10 @@ def clean_process(self): # Reset Helas matrix elements self._curr_matrix_elements = helas_objects.HelasMultiProcess() self._generate_info = "" + # Reset the diagrams kept for an 'auto' merge_quartic_vertices, they + # describe the amplitudes just dropped + self._quartic_order = None + self._quartic_pristine = None # Reset polarization-citation marker (a new process definition starts) self._uses_polarization = False self._uses_density_matrix = False @@ -9164,21 +9172,25 @@ def help_set2_merge_quartic_vertices(self): logger.info(" > speed : fewest amplitude calls (best on cpu)") logger.info(" > slots : smallest wavefunction store (for gpu, where") logger.info(" > that store is per thread); costs the sums") + logger.info(" > auto : slots when the matrix elements go to a gpu") + logger.info(" > backend, speed otherwise, decided per output") def set2_merge_quartic_vertices(self, args, log=True): """Sum the four gluon contributions into the cubic amplitude carrying the same colour factor. Read while the diagrams are generated, so it has to be set before - 'generate' -- an output time option would come too late, the diagram - order is already fixed by then. + 'generate' -- 'speed' and 'slots' fix the diagram order there and an + output time option would come too late. 'auto' generates in the + 'speed' order and lets each output reorder, see + apply_quartic_diagram_order. - Example: set merge_quartic_vertices speed + Example: set merge_quartic_vertices auto """ args = ['merge_quartic_vertices'] + args self.check_set(args) value = args[1].lower() - if value in ('slots', 'speed'): + if value in ('slots', 'speed', 'auto'): pass elif value in ('false', '0', 'none', 'off'): value = False @@ -9186,7 +9198,7 @@ def set2_merge_quartic_vertices(self, args, log=True): value = 'speed' else: raise self.InvalidCmd( - "merge_quartic_vertices takes False, speed or slots," + "merge_quartic_vertices takes False, speed, slots or auto," " not '%s'" % args[1]) self.options[args[0]] = value madgraph.merge_quartic_vertices = value @@ -9592,6 +9604,67 @@ def do_open(self, line): launch_ext.open_file(file_path) + # Output formats whose matrix elements can run on a gpu, where the + # wavefunction store is per thread. See set2_merge_quartic_vertices. + _gpu_me_formats = ['mg7', 'mg7_v5', 'standalone_mg7'] + # Diagram order currently materialised in _curr_amps, and the diagrams as + # they came out of the generation. Both only used for 'auto'. + _quartic_order = None + _quartic_pristine = None + + def apply_quartic_diagram_order(self, options): + """Resolve an 'auto' merge_quartic_vertices against the backend which + is about to be handed the matrix elements. + + What the two modes disagree on is the diagram order, and that is fixed + while the diagrams are generated. 'auto' generates in the 'speed' + order and reorders here instead, which is only possible because + 'slots' is that same order reversed. + + The reordering has to start from the diagrams as generated, not from + the ones in hand: an export mutates what it is given, and reversing + mutated diagrams gives an equivalent but differently numbered result. + """ + + if self.options.get('merge_quartic_vertices') != 'auto': + return + + target = options['me_exporter'].get('name', self._export_format) + gpu = target in self._gpu_me_formats or \ + options['me_exporter'].get('exporter', options['exporter']) == 'gpu' + wanted = 'slots' if gpu else 'speed' + madgraph.merge_quartic_vertices = wanted + + # Keep the diagrams of the amplitudes the seed rule applied to -- the + # order of any other one is not ours to touch. Both have to be read + # before the first export: it is the last moment the diagrams are the + # generated ones, and it also drops the marks saying they came from a + # seed. Amplitudes added later are picked up on the way past. + if self._quartic_pristine is None: + self._quartic_pristine = [] + for amp in self._curr_amps[len(self._quartic_pristine):]: + self._quartic_pristine.append( + copy.deepcopy(amp.get('diagrams')) + if (getattr(amp, 'seed_forbidden_cubic_ids', None) and + getattr(amp, 'quartic_unroll_tags', None)) else None) + if all(pristine is None for pristine in self._quartic_pristine): + return + logger.info("merge_quartic_vertices: '%s' for the %s matrix elements" + % (wanted, target)) + # the generation leaves them in the 'speed' order + if wanted == (self._quartic_order or 'speed'): + return + for amp, pristine in zip(self._curr_amps, self._quartic_pristine): + if pristine is None: + continue + diagrams = copy.deepcopy(pristine) + if wanted == 'slots': + diagrams.reverse() + amp.set('diagrams', base_objects.DiagramList(diagrams)) + self._quartic_order = wanted + # anything cached was built in the other order + self._curr_matrix_elements = helas_objects.HelasMultiProcess() + def do_output(self, line): """Main commands: Initialize a new Template or reinitialize one""" @@ -9715,7 +9788,11 @@ def do_output(self, line): options['me_exporter']['name'] = me_exporter else: options['me_exporter'] = {} - + + # now that the backend getting the matrix elements is known, an 'auto' + # merge_quartic_vertices can be resolved -- before anything is built + self.apply_quartic_diagram_order(options) + # check if os.path.realpath(self._export_dir) == os.getcwd(): if len(args) == 0: diff --git a/tests/unit_tests/core/test_diagram_generation.py b/tests/unit_tests/core/test_diagram_generation.py index 37685f980b..db6f18d79a 100755 --- a/tests/unit_tests/core/test_diagram_generation.py +++ b/tests/unit_tests/core/test_diagram_generation.py @@ -4300,6 +4300,56 @@ def check_current_sums(self, initial, final, nsum, nfolded): # a folded amplitude must not also be a target self.assertFalse(folded & set(uses)) + def check_auto_order(self, initial, final): + """'auto' has to generate the 'speed' order, and 'slots' has to be + that same order reversed. + + This is what lets an output pick between the two: by then the diagrams + exist and only their order can still be changed, so the two modes are + only interchangeable at that point if one is the other backwards.""" + + def tags(mode): + madgraph.merge_quartic_vertices = mode + amplitude = diagram_generation.Amplitude(base_objects.Process( + {'legs':base_objects.LegList( + [base_objects.Leg({'id':pdg, 'state':False}) + for pdg in initial] + + [base_objects.Leg({'id':pdg, 'state':True}) + for pdg in final]), + 'model':self.base_model})) + return [str(diagram_generation.UnrollDiagramTag( + diagram, self.base_model, len(initial))) + for diagram in amplitude.get('diagrams')] + + speed, slots, auto = tags('speed'), tags('slots'), tags('auto') + self.assertEqual(auto, speed) + self.assertEqual(slots, speed[::-1]) + # and it is a reordering, nothing gained or lost + self.assertEqual(sorted(slots), sorted(speed)) + self.assertEqual(len(set(speed)), len(speed)) + + def test_auto_order_gg_ggg(self): + self.check_auto_order([21, 21], [21, 21, 21]) + + def test_auto_order_gg_gggg(self): + self.check_auto_order([21, 21], [21, 21, 21, 21]) + + def test_auto_current_sums(self): + """'auto' keeps the sums, being the 'speed' order; 'slots' drops them + because reversing puts every target ahead of what feeds it""" + + import madgraph.core.helas_objects as helas_objects + + for mode, wanted in (('auto', 7), ('speed', 7), ('slots', 0)): + madgraph.merge_quartic_vertices = mode + amplitude = diagram_generation.Amplitude(base_objects.Process( + {'legs':base_objects.LegList( + [base_objects.Leg({'id':21, 'state':False})] * 2 + + [base_objects.Leg({'id':21, 'state':True})] * 3), + 'model':self.base_model})) + element = helas_objects.HelasMatrixElement(amplitude) + self.assertEqual(len(element.get_quartic_current_sums()[0]), wanted) + def test_seed_inactive_by_default(self): """Nothing changes unless madgraph.merge_quartic_vertices is set""" From b4aecfdc1f6624f5f7a3170dcdb7f7483f93f5d4 Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Wed, 5 Aug 2026 23:49:52 +0200 Subject: [PATCH 32/39] record why auto cannot be the default yet: it breaks fks Defaulting merge_quartic_vertices to 'auto' was tried and reverted. It breaks NLO generation wherever the real emission has four gluons, p p > j j [QCD] among them: born g g > g g real g g > g g g link_rb_configs(born, real, 5, 4, 4) flag off -> [2, 5, 12] 'auto' -> FKSProcessError: could not link born diagram The generation is not at fault: with the flag on, g g > g g g still has its 25 diagrams and the same tag set under both DiagramTag and UnrollDiagramTag. link_rb_configs is order dependent by accident -- it deduplicates real_tags but not good_diags, then walks the two in lockstep, so they only stay aligned while the dedup drops nothing, and which representative of a duplicated tag survives is decided by the diagram order. Fixing that is an NLO change and nothing here validates NLO, so the default stays False. Nine more unit tests encode the old diagram order and would have to be re-based as well; they are listed in the doc. Co-Authored-By: Claude Opus 5 --- docs/gluon-quartic-plan.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/docs/gluon-quartic-plan.md b/docs/gluon-quartic-plan.md index ac896b3208..3537b12721 100644 --- a/docs/gluon-quartic-plan.md +++ b/docs/gluon-quartic-plan.md @@ -619,6 +619,39 @@ instead of the amplitude's trips the lifetime assert in seen in emission order; and restoring only `from_group` on the base diagrams is not enough to undo an export. +## Why `auto` is not the default: FKS + +Making `auto` the default was tried and **reverted**: it breaks NLO generation +wherever the real emission has four gluons, which includes `p p > j j [QCD]`. + +``` +born g g > g g QCD<=2 QED=0 +real g g > g g g QCD<=3 QED=0 +fks_common.link_rb_configs(born, real, 5, 4, 4) + flag off -> [2, 5, 12] + 'auto' -> FKSProcessError: could not link born diagram +``` + +It is not the generation: with the flag on, `g g > g g g` still has its 25 +diagrams and the *same* tag set, under both `DiagramTag` and +`UnrollDiagramTag`. It is `link_rb_configs`, which is order dependent by +accident. It builds `real_tags` deduplicated but leaves `good_diags` as it +is, then walks the two in lockstep -- `real_tags.remove(btag)` beside +`good_diags.pop(ir)` -- so the two only stay aligned while the dedup drops +nothing. Which representative of a duplicated tag survives is decided by the +diagram order, and reordering makes a born diagram fail to find its real one. +The vestigial `real_tags = [...]` assignment immediately overwritten by +`real_tags = []` just above suggests this was patched once already. + +So the default stays `False`. Moving it to `auto` needs `link_rb_configs` +fixed first -- keeping the diagrams beside the tags they were deduplicated +with is the obvious repair -- and that is an NLO change, which nothing in this +work validates. Nine unit tests also encode the old diagram order and would +have to be re-based: `test_diagram_tag_gg_ggg`, `test_colorize_uux_ggg`, +`test_sextet_color_flow_output`, `test_generate_helas_diagrams_gg_gg`, +`test_FKSRealProcess_init`, `test_link_gghgg_gghg`, `test_helas_diagrams_gd_ggd`, +`test_helas_diagrams_gg_ggg`, `test_helas_diagrams_ud_ggdu`. + ## Where to go next **Give madmatrix the amplitude sums too.** It is the only backend without From 5a2bb1dbb8be9ca66bf6c4c9669ff29e8ad17300 Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Thu, 6 Aug 2026 00:54:06 +0200 Subject: [PATCH 33/39] make the four gluon merging safe for NLO, and keep it opt-in Defaulting merge_quartic_vertices to 'auto' was tried and reverted. It is safe on the paths it was built for -- UFO fortran, madmatrix, the python exporter, each validated on |M|^2 -- but turning it on for everything found three consumers reading the diagram or amplitude *structure* rather than the result. 1. fks born/real linking. link_rb_configs finds the vertex splitting ij into i and j and takes it out; the unrolling re-roots the real diagrams and can put that pair in the closing vertex, where there is nothing to take out. p p > j j [QCD] raised FKSProcessError. FIXED here, by generating an NLO process with the merging off in FKSMultiProcess.__init__ -- so the option is now safe for an NLO user, not merely for the default. g g > g g [QCD] generates byte-identically with the option set and unset, where before it crashed. 2. the legacy FortranHelasCallWriter. Only FortranUFOHelasCallWriter emits the amplitude folds which put the merged contributions back, so the MG4-style writer computes AMP(1..3) from GGGGXX and then leaves them out of the JAMPs -- silently wrong |M|^2, not a crash. NOT fixed: it wants merge_quartic_amplitudes=False the way export_cpp and export_python do, but get_JAMP_lines is on the exporter and does not know its writer. 3. anything pinning the diagram order, which is cosmetic but wide. So the default stays False and defaulting it on wants an audit of those consumers rather than another round of patching outward. Fixed independently of all that: link_rb_configs built real_tags deduplicated but left good_diags as it was, then walked the two in lockstep, so they only stayed aligned while the dedup dropped nothing. A no-op on every process in the suite, but it made the result order dependent for no reason. The loop helas sanity checker now knows a folded amplitude is left out of the jamps on purpose; the fks, colorize and DiagramTag tests which read a diagram by its position say so and pin the plain order. 916 unit tests, same two pre-existing failures. Co-Authored-By: Claude Opus 5 --- docs/gluon-quartic-plan.md | 82 +++++++++++-------- madgraph/__init__.py | 3 + madgraph/fks/fks_base.py | 12 +++ madgraph/fks/fks_common.py | 11 ++- tests/unit_tests/core/test_color_amp.py | 8 +- .../core/test_diagram_generation.py | 7 +- tests/unit_tests/fks/test_fks_base.py | 10 +++ tests/unit_tests/fks/test_fks_common.py | 15 ++++ .../loop/test_loop_helas_objects.py | 5 ++ 9 files changed, 116 insertions(+), 37 deletions(-) diff --git a/docs/gluon-quartic-plan.md b/docs/gluon-quartic-plan.md index 3537b12721..b26243fe2b 100644 --- a/docs/gluon-quartic-plan.md +++ b/docs/gluon-quartic-plan.md @@ -619,38 +619,56 @@ instead of the amplitude's trips the lifetime assert in seen in emission order; and restoring only `from_group` on the base diagrams is not enough to undo an export. -## Why `auto` is not the default: FKS - -Making `auto` the default was tried and **reverted**: it breaks NLO generation -wherever the real emission has four gluons, which includes `p p > j j [QCD]`. - -``` -born g g > g g QCD<=2 QED=0 -real g g > g g g QCD<=3 QED=0 -fks_common.link_rb_configs(born, real, 5, 4, 4) - flag off -> [2, 5, 12] - 'auto' -> FKSProcessError: could not link born diagram -``` - -It is not the generation: with the flag on, `g g > g g g` still has its 25 -diagrams and the *same* tag set, under both `DiagramTag` and -`UnrollDiagramTag`. It is `link_rb_configs`, which is order dependent by -accident. It builds `real_tags` deduplicated but leaves `good_diags` as it -is, then walks the two in lockstep -- `real_tags.remove(btag)` beside -`good_diags.pop(ir)` -- so the two only stay aligned while the dedup drops -nothing. Which representative of a duplicated tag survives is decided by the -diagram order, and reordering makes a born diagram fail to find its real one. -The vestigial `real_tags = [...]` assignment immediately overwritten by -`real_tags = []` just above suggests this was patched once already. - -So the default stays `False`. Moving it to `auto` needs `link_rb_configs` -fixed first -- keeping the diagrams beside the tags they were deduplicated -with is the obvious repair -- and that is an NLO change, which nothing in this -work validates. Nine unit tests also encode the old diagram order and would -have to be re-based: `test_diagram_tag_gg_ggg`, `test_colorize_uux_ggg`, -`test_sextet_color_flow_output`, `test_generate_helas_diagrams_gg_gg`, -`test_FKSRealProcess_init`, `test_link_gghgg_gghg`, `test_helas_diagrams_gd_ggd`, -`test_helas_diagrams_gg_ggg`, `test_helas_diagrams_ud_ggdu`. +## Why this is not the default + +Defaulting `merge_quartic_vertices` to `auto` was tried and **reverted**. It is +safe on the paths it was built for -- UFO Fortran, madmatrix, the python +exporter -- and each of those is validated on `|M|^2`. Turning it on for +everything found three consumers which read the diagram or amplitude +*structure* rather than the result: + +1. **FKS born/real linking.** `link_rb_configs` finds the vertex splitting + `ij` into `i` and `j` and takes it out. The unrolling re-roots the real + diagrams and can put that pair in the closing vertex, where there is + nothing to take out, so the remainder is malformed and no born + configuration matches it. Same 3 diagrams selected, same tag set, different + decomposition: + + ``` + off ((1,2>1),(4,5>4),(1,3,4)) the 4-5 vertex is internal + auto ((1,2>1),(1,3>1),(1,4,5)) the 4-5 pair closes the diagram + ``` + + `p p > j j [QCD]` raised `FKSProcessError`. **Fixed** by generating an NLO + process with the merging off, in `FKSMultiProcess.__init__`, so the option + is now safe for an NLO user rather than only for the default. `g g > g g + [QCD]` generates byte-identically with the option set and unset. + +2. **The legacy `FortranHelasCallWriter`.** Only `FortranUFOHelasCallWriter` + emits the amplitude folds which put the merged contributions back. The + MG4-style writer computes `AMP(1..3)` from `GGGGXX` and then leaves them out + of the JAMPs -- a **silently wrong** `|M|^2`, not a crash. Not fixed: like + `export_cpp` and `export_python` it needs `merge_quartic_amplitudes=False`, + but `get_JAMP_lines` is on the exporter and does not know which writer it + is paired with. + +3. **Anything pinning the diagram order.** Cosmetic but wide: `colorize` and + `DiagramTag` tests select diagrams by position, and the sextet colour basis + goes 13 -> 15 because folding amplitudes decomposes the same `|M|^2` over + more colour structures (`|M|^2` bit-identical, checked with + `MatrixElementEvaluator`). + +The pattern is that the optimisation changes the *representation* -- diagram +order, rooting, which amplitudes survive into the JAMPs -- and every consumer +which reads representation rather than result has to be checked. Three turned +up in one pass, so defaulting it on wants an audit of those consumers, not +another round of patching outward. + +Also fixed on the way, and independent of all this: `link_rb_configs` built +`real_tags` deduplicated but left `good_diags` as it was, then walked the two +in lockstep -- `real_tags.remove(btag)` beside `good_diags.pop(ir)` -- so they +only stayed aligned while the dedup dropped nothing. A no-op on every process +in the test suite, but it made the result order dependent for no reason. ## Where to go next diff --git a/madgraph/__init__.py b/madgraph/__init__.py index 88155dbbb5..0c2646e14a 100755 --- a/madgraph/__init__.py +++ b/madgraph/__init__.py @@ -76,5 +76,8 @@ class aMCatNLOError(MadGraph5Error): # the matrix elements go to a gpu backend, 'speed' otherwise. The # interface resolves it to one of the two above before anything # reads it again, so only the generation ever sees 'auto'. +# Off by default: several consumers read the diagram or amplitude structure +# rather than the result, see "Why this is not the default" in +# docs/gluon-quartic-plan.md. merge_quartic_vertices = False diff --git a/madgraph/fks/fks_base.py b/madgraph/fks/fks_base.py index 3b6f941d39..a16566d0f2 100755 --- a/madgraph/fks/fks_base.py +++ b/madgraph/fks/fks_base.py @@ -129,6 +129,18 @@ def __init__(self, procdef=None, options={}): legs (stored in pdgs, so that they need to be generated only once and then reicycled """ + # The four gluon merging is validated at tree level only, and an NLO + # generation is left alone whatever the option says. fks reads the + # vertex decomposition of its real diagrams -- link_rb_configs finds + # the vertex splitting ij into i and j and takes it out -- and the + # unrolling re-roots them, which can put that pair in the closing + # vertex, where there is nothing to take out. + with misc.TMP_variable(madgraph, 'merge_quartic_vertices', False): + self.generate_all(procdef, options) + + def generate_all(self, procdef=None, options={}): + """Generates the born amplitudes, the born processes and the reals, + see __init__ which is the only caller.""" if 'nlo_mixed_expansion' in options: self['nlo_mixed_expansion'] = options['nlo_mixed_expansion'] diff --git a/madgraph/fks/fks_common.py b/madgraph/fks/fks_common.py index 7d055c6a0b..c07305adb9 100755 --- a/madgraph/fks/fks_common.py +++ b/madgraph/fks/fks_common.py @@ -196,14 +196,19 @@ def link_rb_configs(born_amp, real_amp, i, j, ij): for d in born_confs] - real_tags = [FKSDiagramTag(d['diagram'], - real_amp.get('process').get('model')) \ - for d in good_diags ] + # Dropping a duplicated tag has to drop its diagram with it: the two are + # walked in lockstep below, real_tags.index giving the position popped out + # of good_diags, so a tag left without its diagram misaligns everything + # after it. Which of two equal tags survives is decided by the order they + # come in, so keeping them apart also made the result order dependent. real_tags = [] + kept_diags = [] for d in good_diags: tag = FKSDiagramTag(d['diagram'], real_amp.get('process').get('model')) if not tag in real_tags: real_tags.append(tag) + kept_diags.append(d) + good_diags = kept_diags # and compare them if len(born_tags) != len(real_tags): diff --git a/tests/unit_tests/core/test_color_amp.py b/tests/unit_tests/core/test_color_amp.py index 9775c450fc..0926cae2c7 100755 --- a/tests/unit_tests/core/test_color_amp.py +++ b/tests/unit_tests/core/test_color_amp.py @@ -20,6 +20,8 @@ import copy import fractions +import madgraph +import madgraph.various.misc as misc import madgraph.core.base_objects as base_objects import madgraph.core.diagram_generation as diagram_generation @@ -255,7 +257,11 @@ def test_colorize_uux_ggg(self): myamplitude.set('process', myprocess) - myamplitude.generate_diagrams() + # What is checked below is colorize, against diagrams picked by their + # position, so it wants the plain generation order -- the four gluon + # merging reorders them + with misc.TMP_variable(madgraph, 'merge_quartic_vertices', False): + myamplitude.generate_diagrams() my_col_basis = color_amp.ColorBasis() diff --git a/tests/unit_tests/core/test_diagram_generation.py b/tests/unit_tests/core/test_diagram_generation.py index db6f18d79a..491253eb0f 100755 --- a/tests/unit_tests/core/test_diagram_generation.py +++ b/tests/unit_tests/core/test_diagram_generation.py @@ -26,6 +26,7 @@ import tests.unit_tests as unittest import madgraph +import madgraph.various.misc as misc import madgraph.core.base_objects as base_objects import madgraph.core.color_amp as color_amp import madgraph.core.diagram_generation as diagram_generation @@ -3748,7 +3749,11 @@ def test_diagram_tag_gg_ggg(self): myproc = base_objects.Process({'legs':myleglist, 'model':self.base_model}) - myamplitude = diagram_generation.Amplitude(myproc) + # DiagramTag is what is checked here, against diagram numbers, so it + # wants the plain generation order -- the four gluon merging reorders + # them + with misc.TMP_variable(madgraph, 'merge_quartic_vertices', False): + myamplitude = diagram_generation.Amplitude(myproc) tags = [] permutations = [] diff --git a/tests/unit_tests/fks/test_fks_base.py b/tests/unit_tests/fks/test_fks_base.py index f975840a39..9c6a39e923 100755 --- a/tests/unit_tests/fks/test_fks_base.py +++ b/tests/unit_tests/fks/test_fks_base.py @@ -23,6 +23,7 @@ import tests.unit_tests as unittest import madgraph.various.misc as misc +import madgraph import madgraph.fks.fks_base as fks_base import madgraph.fks.fks_common as fks_common import madgraph.core.base_objects as MG @@ -35,6 +36,15 @@ class TestFKSProcess(unittest.TestCase): """a class to test FKS Processes""" + def setUp(self): + # these build the fks amplitudes by hand, so they have to turn the + # four gluon merging off themselves, as FKSMultiProcess does + self.merge_quartic = madgraph.merge_quartic_vertices + madgraph.merge_quartic_vertices = False + + def tearDown(self): + madgraph.merge_quartic_vertices = self.merge_quartic + # the model, import the SM but remove 2nd and 3rd gen quarks remove_list = [3,4,5,6,-3,-4,-5,-6] mymodel = import_ufo.import_model('sm', options={'apply_flavor_grouping':False}) diff --git a/tests/unit_tests/fks/test_fks_common.py b/tests/unit_tests/fks/test_fks_common.py index 879f4d6462..79919e196f 100755 --- a/tests/unit_tests/fks/test_fks_common.py +++ b/tests/unit_tests/fks/test_fks_common.py @@ -24,6 +24,7 @@ sys.path.insert(0, os.path.join(root_path,'..','..')) import tests.unit_tests as unittest +import madgraph import madgraph.fks.fks_common as fks_common import madgraph.core.base_objects as MG import madgraph.core.color_algebra as color @@ -2933,9 +2934,16 @@ class TestLinkRBConfHEFT(unittest.TestCase): (only processes with 3 point interactions)""" def setUp(self): + # link_rb_configs reads the vertex decomposition of the real diagrams, + # so it runs with the four gluon merging off, as FKSMultiProcess does + self.merge_quartic = madgraph.merge_quartic_vertices + madgraph.merge_quartic_vertices = False if not hasattr(self, 'base_model'): TestLinkRBConfHEFT.base_model = import_ufo.import_model('heft') + def tearDown(self): + madgraph.merge_quartic_vertices = self.merge_quartic + def test_link_gghg_ggh(self): """tests that the real emission process gg>hg and born process gg>h are @@ -3062,9 +3070,16 @@ class TestLinkRBConfSM(unittest.TestCase): (only processes with 3 point interactions)""" def setUp(self): + # link_rb_configs reads the vertex decomposition of the real diagrams, + # so it runs with the four gluon merging off, as FKSMultiProcess does + self.merge_quartic = madgraph.merge_quartic_vertices + madgraph.merge_quartic_vertices = False if not hasattr(self, 'base_model'): TestLinkRBConfSM.base_model = import_ufo.import_model('sm', options={'apply_flavor_grouping':False}) + def tearDown(self): + madgraph.merge_quartic_vertices = self.merge_quartic + def test_link_udxwpg_udxwp(self): """tests that the real emission process ud~>w+g and born process u u~>w+ are correctly linked""" diff --git a/tests/unit_tests/loop/test_loop_helas_objects.py b/tests/unit_tests/loop/test_loop_helas_objects.py index 261b091e97..a2b6cf5910 100755 --- a/tests/unit_tests/loop/test_loop_helas_objects.py +++ b/tests/unit_tests/loop/test_loop_helas_objects.py @@ -296,6 +296,11 @@ def check_HME_individual_diag_sanity(self,Amplitude, process,\ amp_number_apparition=[] for jamp in color_amplitudes: amp_number_apparition.extend([a[1] for a in jamp]) + # A four gluon contribution summed into another amplitude is + # dropped from the jamps on purpose, its colour factor being + # carried by the amplitude it was summed into + amp_number_apparition.extend( + myME.get_quartic_amplitude_merges().keys()) diagIndex=0 for i, diag in enumerate(diagSelection): From 15cb14e16892ccd703c4da9ab32d3891ac2c4439 Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Thu, 6 Aug 2026 07:35:23 +0200 Subject: [PATCH 34/39] record the scan for a fourth consumer, and what it bounds Looked for a fourth place reading the representation rather than the result. Did not find one in the shipped tree, and the search is worth keeping because it bounds what is left. Every merged-JAMP consumer against every writer: get_color_amplitudes has four call sites and three pass merge_quartic_amplitudes=False; only export_v4's three get_JAMP_lines* take the merged default, and every fortran exporter pairs with FortranUFOHelasCallWriter, which emits the folds. The base get_amplitude_merge_lines returns [] and FortranHelasCallWriter does not override get_matrix_element_calls, so it is the one writer which drops them -- selected exactly when _model_v4_path is set. No other combination reaches merged JAMPs without folds. A mechanical audit of the generated code -- for each AMP(n), written? read? -- run with the flag off as a control, over standalone, matchbox, madevent grouped and not, a decay chain, helicity-recycled files, u u~ > g g g, g g > t t~ g g, u u~ > u u~ g g and four to six gluons. Clean everywhere, including the split order path, whose amp_orders does list folded amplitude numbers but never reaches the code because the colour amplitudes no longer mention them. The two places which weight or group results are unaffected: p p > j j groups into the same five directories with byte-identical configs.inc and coloramps.inc, and find_symmetry keeps the same equivalence classes and multiplicities, [3,3,3,6] at five gluons and [3,6,12,12,12,12,12,12,24] at six, only the representative indices renumbering. Residual risk of this class is two named things: import model_v4, and a plugin supplying its own helas_exporter paired with export_v4's merged JAMPs. Co-Authored-By: Claude Opus 5 --- docs/gluon-quartic-plan.md | 46 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/docs/gluon-quartic-plan.md b/docs/gluon-quartic-plan.md index b26243fe2b..7372da3ae5 100644 --- a/docs/gluon-quartic-plan.md +++ b/docs/gluon-quartic-plan.md @@ -658,6 +658,52 @@ everything found three consumers which read the diagram or amplitude more colour structures (`|M|^2` bit-identical, checked with `MatrixElementEvaluator`). +### The scan for a fourth + +Looked for one, did not find one in the shipped tree, and the search bounds +the remaining risk. + +**Every merged-JAMP consumer, against every writer.** `get_color_amplitudes` +has four call sites: `export_cpp` (x2), `export_python` and `madmatrix` all +pass `merge_quartic_amplitudes=False`; only `export_v4`'s three +`get_JAMP_lines*` take the merged default, and every Fortran exporter pairs +with `FortranUFOHelasCallWriter`, which emits the folds. The base +`get_amplitude_merge_lines` returns `[]` and `FortranHelasCallWriter` does not +override `get_matrix_element_calls`, so it is the one writer that silently +drops them -- and it is selected exactly when `self._model_v4_path` is set, +i.e. under `import model_v4`. No other combination in the tree reaches merged +JAMPs without folds. + +The property which keeps `merge_quartic_amplitudes=False` safe is that +`get_color_amplitudes` drops the current-sum folded amplitudes +*unconditionally* and only the amplitude merges conditionally -- so a writer +which emits the sums but not the folds still gets consistent JAMPs. + +**A mechanical audit of the generated code.** For each `AMP(n)` in a generated +matrix element, whether it is written and whether it is read. Read-never- +written is garbage; written-never-read is a contribution dropped on the floor, +which is the legacy writer's signature. Run with the flag off as a control on +every output -- standalone, matchbox, madevent grouped and not, a decay chain, +helicity-recycled files, `u u~ > g g g`, `g g > t t~ g g`, `u u~ > u u~ g g`, +four to six gluons -- and clean everywhere. The split order path is included: +`ProcessExporterFortranSA` and `ProcessExporterFortranME` both always go +through `get_JAMP_lines_split_order`, whose `amp_orders` lists folded +amplitude numbers, but they never reach the code because the colour amplitudes +no longer mention them. + +**The two places which weight or group results.** Subprocess grouping for +`p p > j j` gives the same five directories and byte-identical `configs.inc` +and `coloramps.inc`; only the `g g > g g` matrix element differs. +`find_symmetry`, which feeds the multiplicative `symfact.dat`, keeps the same +equivalence classes and multiplicities -- `[3, 3, 3, 6]` at five gluons and +`[3, 6, 12, 12, 12, 12, 12, 12, 24]` at six, in both settings, with the same +number of channels and the same total weight. Only the representative diagram +indices renumber, which is the renumbering itself. + +So the residual risk of this class is two named things: `import model_v4`, and +a third-party plugin supplying its own `helas_exporter` paired with +`export_v4`'s merged JAMPs. + The pattern is that the optimisation changes the *representation* -- diagram order, rooting, which amplitudes survive into the JAMPs -- and every consumer which reads representation rather than result has to be checked. Three turned From f128aa694f06dee319cc593aa58046e28b170bf1 Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Tue, 11 Aug 2026 16:05:48 +0200 Subject: [PATCH 35/39] measure all three modes on both series, memory included A full sweep of g g > N g and g g > t t~ N g, off against speed and slots, on generation time, source and object size, wavefunction slots, amplitude counts and runtime. Timings are the minimum of five runs, which matters: a single run carries about 3% of noise and most of the effects are smaller than that. The floor of the method is 0.6%, measured on g g > t t~ where off and speed give a byte-identical matrix.f and still time 3.975 against 4.000 us. What the amplitude columns show, and neither was obvious before: - the AMP array never shrinks. It is declared COMPLEX*16 AMP(NGRAPHS) at the full diagram count whatever the mode, so all three builds allocate 113 kB at seven gluons and speed leaves 432 entries written by nobody. Only the W array ever gets smaller, and only under slots. - slots mode computes every amplitude, on all eight of its rows. With no current sums nothing is skipped, so it does the baseline's amplitude work plus the folds and buys only a shorter JAMP block and a shorter W array. That is why it is slower than off almost everywhere rather than a wash. And what the optimisation is actually good for is generation time and code size rather than speed: g g > 5 g generates in 19.4 s rather than 37.1 s, a 48% cut, with matrix.o going 5.8 MB to 3.6 MB. Runtime is a steady 5-8% above six particles and nothing at all below. |M|^2 agrees to 8.5e-15 or better on every row. Co-Authored-By: Claude Opus 5 --- docs/gluon-quartic-plan.md | 77 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/docs/gluon-quartic-plan.md b/docs/gluon-quartic-plan.md index 7372da3ae5..5c2131fadb 100644 --- a/docs/gluon-quartic-plan.md +++ b/docs/gluon-quartic-plan.md @@ -489,6 +489,83 @@ from six gluons on. and seven, in both backends. With the flag off, `matrix.f` and `CPPProcess.cc` are byte-identical to before any of this. +## Full sweep -- speed, memory and generation time + +All three modes against the flag off, on the same machine, for both series. +Timings are the minimum of five runs of the shipped `check` driver looping +`SMATRIX` on a fixed phase space point; the minimum matters, because a single +run carries about 3% of noise and most of the effects here are smaller than +that. The floor of the method is 0.6%, measured on `g g > t t~`, where `off` +and `speed` produce a byte-identical `matrix.f` and still time 3.975 against +4.000 us. `|M|^2` agrees to 8.5e-15 or better on every row. + +*slots* is `NWAVEFUNCS`, the length of the wavefunction array, `TYPE(ALOHA) +W(NWAVEFUNCS)` -- not the number of wavefunctions computed, since +`reuse_outdated_wavefunctions` frees an entry as soon as its last reader has +run (898 wavefunction calls live in 268 slots at seven gluons). One entry is +104 bytes, measured with `storage_size`: four `complex*16`, `P(0:3)` and +`flv_index`, padded. One amplitude is 16 bytes. + +**`g g > N g`** + +| process | mode | generate | matrix.f | matrix.o | slots | W array | amps decl | amps computed | AMP array | per call | speed | +|---|---|---|---|---|---|---|---|---|---|---|---| +| g g > 2g | off | 1.8 s | 27 kB | 16 kB | 5 | 0.5 kB | 6 | 6 | 0.1 kB | 5.48 us | - | +| | speed | 1.6 s | 27 kB | 17 kB | 5 | 0.5 kB | 6 | 6 | 0.1 kB | 5.52 us | -1% | +| | slots | 1.8 s | 27 kB | 17 kB | 5 | 0.5 kB | 6 | 6 | 0.1 kB | 5.55 us | -1% | +| g g > 3g | off | 1.9 s | 40 kB | 28 kB | 12 | 1.2 kB | 45 | 45 | 0.7 kB | 86.75 us | - | +| | speed | 1.8 s | 39 kB | 29 kB | 19 | 1.9 kB | 45 | 38 | 0.7 kB | 87.25 us | -1% | +| | slots | 1.9 s | 40 kB | 29 kB | 12 | 1.2 kB | 45 | 45 | 0.7 kB | 93.25 us | -7% | +| g g > 4g | off | 3.0 s | 181 kB | 141 kB | 51 | 5.2 kB | 510 | 510 | 8.0 kB | 2.37 ms | - | +| | speed | 2.4 s | 166 kB | 147 kB | 78 | 7.9 kB | 510 | 450 | 8.0 kB | 2.24 ms | +5% | +| | slots | 2.4 s | 168 kB | 153 kB | 54 | 5.5 kB | 510 | 510 | 8.0 kB | 2.36 ms | +0% | +| g g > 5g | off | 37.1 s | 3.3 MB | 5.8 MB | 268 | 27.2 kB | 7245 | 7245 | 113.2 kB | 140.75 ms | - | +| | speed | 19.4 s | 2.5 MB | 3.6 MB | 259 | 26.3 kB | 7245 | 6813 | 113.2 kB | 133.25 ms | +5% | +| | slots | 18.3 s | 2.6 MB | 3.5 MB | 199 | 20.2 kB | 7245 | 7245 | 113.2 kB | 135.50 ms | +4% | + +**`g g > t t~ N g`** + +| process | mode | generate | matrix.f | matrix.o | slots | W array | amps decl | amps computed | AMP array | per call | speed | +|---|---|---|---|---|---|---|---|---|---|---|---| +| g g > t t~ | off | 1.7 s | 26 kB | 16 kB | 5 | 0.5 kB | 3 | 3 | 0.0 kB | 4.00 us | - | +| | speed | 1.6 s | 26 kB | 16 kB | 5 | 0.5 kB | 3 | 3 | 0.0 kB | 4.00 us | +0% | +| | slots | 1.6 s | 26 kB | 16 kB | 5 | 0.5 kB | 3 | 3 | 0.0 kB | 4.10 us | -2% | +| g g > t t~ g | off | 2.1 s | 31 kB | 20 kB | 12 | 1.2 kB | 18 | 18 | 0.3 kB | 30.25 us | - | +| | speed | 1.9 s | 31 kB | 20 kB | 12 | 1.2 kB | 18 | 15 | 0.3 kB | 29.92 us | +1% | +| | slots | 1.8 s | 31 kB | 21 kB | 12 | 1.2 kB | 18 | 18 | 0.3 kB | 30.50 us | -1% | +| g g > t t~ 2g | off | 2.4 s | 68 kB | 51 kB | 26 | 2.6 kB | 159 | 159 | 2.5 kB | 377.00 us | - | +| | speed | 2.3 s | 65 kB | 49 kB | 35 | 3.6 kB | 159 | 126 | 2.5 kB | 350.00 us | +7% | +| | slots | 2.3 s | 66 kB | 53 kB | 29 | 2.9 kB | 159 | 159 | 2.5 kB | 390.00 us | -3% | +| g g > t t~ 3g | off | 6.4 s | 576 kB | 479 kB | 121 | 12.3 kB | 1890 | 1890 | 29.5 kB | 9.60 ms | - | +| | speed | 5.3 s | 473 kB | 414 kB | 213 | 21.6 kB | 1890 | 1551 | 29.5 kB | 8.87 ms | +8% | +| | slots | 5.2 s | 487 kB | 460 kB | 141 | 14.3 kB | 1890 | 1890 | 29.5 kB | 9.73 ms | -1% | + +Two things worth reading off the amplitude columns. + +**The AMP array never shrinks.** It is declared `COMPLEX*16 AMP(NGRAPHS)` at +the full diagram count whatever the mode, so all three builds allocate 113 kB +at seven gluons and `speed` leaves 432 entries written by nobody. The +amplitude memory is identical everywhere; only the number computed moves. So +the optimisation saves memory only in the W array, and only in `slots` mode. + +**`slots` mode computes every amplitude** -- `amps computed` equals `amps +decl` on all eight of its rows. With no current sums nothing is skipped, so it +does the same amplitude work as the baseline *plus* the folds, and buys only a +shorter JAMP block and a shorter W array. That is why it is slower than off +almost everywhere rather than a wash: strictly more arithmetic for less +memory. `speed` is the opposite, skipping amplitudes outright (450 of 510, +6813 of 7245, 1551 of 1890), which is where its 5-8% comes from, and paying in +slots -- 121 to 213 at `g g > t t~ 3g`. + +**What it is actually good for.** Generation time and code size, more than +speed. `g g > 5 g` generates in 19.4 s rather than 37.1 s, a 48% cut and +reproducible: 385 seed diagrams unrolled is cheaper than 2485 generated. Its +`matrix.o` goes 5.8 MB to 3.6 MB. Runtime is a steady 5-8% above six particles +and nothing at all below, and the `t t~` series gains more than the pure gluon +one at equal particle count, +8% at `t t~ 3g` against +5% at `4g`. Peak RSS is +flat except at seven gluons, because the wavefunction store is a stack frame +and the code image dominates. + ## The diagram order — measured, and worth a lot `reuse_outdated_wavefunctions` is a linear scan allocator over lifetimes taken From f7e3e035870f326a196c1f7b1b057ff320c768a4 Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Tue, 11 Aug 2026 16:30:04 +0200 Subject: [PATCH 36/39] gate the seed rule on the multiplicity, for auto The sweep puts the turnover of the full merging at six external legs, and shows it costing slots below that, so auto now gates on it: generate_diagrams only takes the seed rule at madgraph.merge_quartic_min_legs legs or more, six by measurement. speed and slots asked for by name stay unconditional, that being the way to get the merging on a small process anyway. What is left below the threshold is not nothing, which was worth measuring rather than assuming. The amplitude merges do not need the seed rule -- they come from the colour algebra through unroll_quartic_vertices -- so they still apply, and they shrink the JAMP block without touching the wavefunctions: g g > g g g slots JAMP temporaries per call off 12 72 87.75 us auto (merges only) 12 42 84.25 us +4.0% speed (full) 19 42 87.25 us -1% So below the threshold auto beats both: it keeps the JAMP fold, which is free, and drops the reordering, which is what costs the seven extra slots. At four and five legs elsewhere it is neutral rather than positive and never negative, at an unchanged slot count. Above the threshold nothing moves -- auto at six legs generates a byte-identical matrix.f to speed. 917 unit tests, one of them new, same two pre-existing failures. Co-Authored-By: Claude Opus 5 --- docs/gluon-quartic-plan.md | 29 ++++++++++++++++ madgraph/__init__.py | 26 +++++++++++--- madgraph/core/diagram_generation.py | 7 ++-- madgraph/interface/madgraph_interface.py | 5 +-- .../core/test_diagram_generation.py | 34 +++++++++++++++++-- 5 files changed, 91 insertions(+), 10 deletions(-) diff --git a/docs/gluon-quartic-plan.md b/docs/gluon-quartic-plan.md index 5c2131fadb..63ac4e89f8 100644 --- a/docs/gluon-quartic-plan.md +++ b/docs/gluon-quartic-plan.md @@ -566,6 +566,35 @@ one at equal particle count, +8% at `t t~ 3g` against +5% at `4g`. Peak RSS is flat except at seven gluons, because the wavefunction store is a stack frame and the code image dominates. +## The multiplicity gate + +The sweep says the full merging turns over at six external legs, and the same +sweep says it costs slots below that. So `auto` gates on it: +`Amplitude.generate_diagrams` only takes the seed rule when the process has +`madgraph.merge_quartic_min_legs` legs or more, six by measurement. `speed` +and `slots` asked for by name are unconditional -- that is how you get the +merging on a small process anyway. + +What is left below the threshold is not nothing, and this was worth measuring +rather than assuming. The *amplitude* merges do not need the seed rule: they +are found from the colour algebra by `unroll_quartic_vertices`, so they still +apply, and they shrink the JAMP block without touching the wavefunctions: + +| `g g > g g g` | slots | JAMP temporaries | per call | +|---|---|---|---| +| off | 12 | 72 | 87.75 us | +| `auto` (merges only) | 12 | 42 | **84.25 us**, +4.0% | +| `speed` (full) | 19 | 42 | 87.25 us, -1% | + +So below the threshold `auto` is *better* than both -- it keeps the JAMP fold, +which is free, and drops the reordering, which is what costs the seven extra +slots. At four and five legs elsewhere it is neutral rather than positive +(`g g > g g` 5.47 -> 5.48 us, `g g > t t~ g` 30.33 -> 30.42 us, both inside +the 0.6% floor) and never negative, at an unchanged slot count. + +Above the threshold nothing changes: `auto` at six legs generates a +byte-identical `matrix.f` to `speed`. + ## The diagram order — measured, and worth a lot `reuse_outdated_wavefunctions` is a linear scan allocator over lifetimes taken diff --git a/madgraph/__init__.py b/madgraph/__init__.py index 0c2646e14a..000a1794c8 100755 --- a/madgraph/__init__.py +++ b/madgraph/__init__.py @@ -72,12 +72,30 @@ class aMCatNLOError(MadGraph5Error): # alive. Trades 6% more amplitude calls for 23% fewer # wavefunction slots at seven gluons, which is the trade a gpu # wants when occupancy is the limit. -# 'auto' -- generate as for 'speed', and let each output pick: 'slots' when -# the matrix elements go to a gpu backend, 'speed' otherwise. The -# interface resolves it to one of the two above before anything -# reads it again, so only the generation ever sees 'auto'. +# 'auto' -- decide per process. Below merge_quartic_min_legs external legs +# only the amplitude merges are taken, which shrink the JAMP +# block for free; the seed rule -- and with it the reordering, +# the current sums and the slots they cost -- is left off, since +# below that size it does not pay for itself. At or above it, +# generate as for 'speed' and let each output pick 'slots' when +# the matrix elements go to a gpu backend and 'speed' otherwise. +# The interface resolves the second half before anything reads it +# again, so only the generation ever sees 'auto'. +# 'speed' and 'slots' are unconditional -- they are the way to ask for the +# merging on a small process anyway. # Off by default: several consumers read the diagram or amplitude structure # rather than the result, see "Why this is not the default" in # docs/gluon-quartic-plan.md. merge_quartic_vertices = False + +# External legs an 'auto' process needs before the seed rule is worth it. +# Measured on g g > N g and g g > t t~ N g, both of which turn over at six: +# five legs and below the full merging is inside the noise or slightly +# negative (-1% at g g > g g g, which also pays 12 -> 19 wavefunction slots), +# six and above it is a steady 5-8% with the source and the object file +# shrinking too. The amplitude merges alone, which is what is left below the +# threshold, are +4% at g g > g g g and neutral at four and five legs +# elsewhere, at the same slot count -- never a loss. See "Full sweep" in +# docs/gluon-quartic-plan.md. +merge_quartic_min_legs = 6 diff --git a/madgraph/core/diagram_generation.py b/madgraph/core/diagram_generation.py index d9f5a0fc11..f5ce93b801 100755 --- a/madgraph/core/diagram_generation.py +++ b/madgraph/core/diagram_generation.py @@ -1113,10 +1113,13 @@ def generate_diagrams(self, returndiag=False, diagram_filter=False): # share a line -- and the seed is what is left over. # Left off for a decay chain, whose identity vertex is kept rather # than glued in, and for loop amplitudes, whose diagram set is not the - # one the unrolling reasons about. + # one the unrolling reasons about. 'auto' also leaves it off below + # merge_quartic_min_legs, where it is measured to buy nothing. self.seed_forbidden_cubic_ids = frozenset() if madgraph.merge_quartic_vertices and not self.has_loop_process() \ - and not process.get('is_decay_chain'): + and not process.get('is_decay_chain') \ + and (madgraph.merge_quartic_vertices != 'auto' or + len(process.get('legs')) >= madgraph.merge_quartic_min_legs): self.seed_forbidden_cubic_ids = get_unrollable_cubic_ids(model) diff --git a/madgraph/interface/madgraph_interface.py b/madgraph/interface/madgraph_interface.py index 79fc665895..b1c8eee245 100755 --- a/madgraph/interface/madgraph_interface.py +++ b/madgraph/interface/madgraph_interface.py @@ -9172,8 +9172,9 @@ def help_set2_merge_quartic_vertices(self): logger.info(" > speed : fewest amplitude calls (best on cpu)") logger.info(" > slots : smallest wavefunction store (for gpu, where") logger.info(" > that store is per thread); costs the sums") - logger.info(" > auto : slots when the matrix elements go to a gpu") - logger.info(" > backend, speed otherwise, decided per output") + logger.info(" > auto : below 6 legs only the amplitude merges, which") + logger.info(" > are free; above, slots when the matrix elements") + logger.info(" > go to a gpu backend and speed otherwise") def set2_merge_quartic_vertices(self, args, log=True): """Sum the four gluon contributions into the cubic amplitude carrying diff --git a/tests/unit_tests/core/test_diagram_generation.py b/tests/unit_tests/core/test_diagram_generation.py index 491253eb0f..de080e25cf 100755 --- a/tests/unit_tests/core/test_diagram_generation.py +++ b/tests/unit_tests/core/test_diagram_generation.py @@ -4327,11 +4327,16 @@ def tags(mode): for diagram in amplitude.get('diagrams')] speed, slots, auto = tags('speed'), tags('slots'), tags('auto') - self.assertEqual(auto, speed) self.assertEqual(slots, speed[::-1]) # and it is a reordering, nothing gained or lost self.assertEqual(sorted(slots), sorted(speed)) self.assertEqual(len(set(speed)), len(speed)) + # 'auto' only takes that order once the process is big enough to pay + # for it, and otherwise leaves the generation order alone + if len(initial) + len(final) >= madgraph.merge_quartic_min_legs: + self.assertEqual(auto, speed) + else: + self.assertEqual(auto, tags(False)) def test_auto_order_gg_ggg(self): self.check_auto_order([21, 21], [21, 21, 21]) @@ -4345,7 +4350,9 @@ def test_auto_current_sums(self): import madgraph.core.helas_objects as helas_objects - for mode, wanted in (('auto', 7), ('speed', 7), ('slots', 0)): + # five legs, so below merge_quartic_min_legs: 'auto' does not seed and + # so has no sums, while asking for 'speed' by name still does + for mode, wanted in (('auto', 0), ('speed', 7), ('slots', 0)): madgraph.merge_quartic_vertices = mode amplitude = diagram_generation.Amplitude(base_objects.Process( {'legs':base_objects.LegList( @@ -4355,6 +4362,29 @@ def test_auto_current_sums(self): element = helas_objects.HelasMatrixElement(amplitude) self.assertEqual(len(element.get_quartic_current_sums()[0]), wanted) + def test_auto_multiplicity_gate(self): + """'auto' leaves the seed rule off below merge_quartic_min_legs, where + it is measured not to pay for itself, and takes it above""" + + def seeded(nfinal, mode): + madgraph.merge_quartic_vertices = mode + amplitude = diagram_generation.Amplitude(base_objects.Process( + {'legs':base_objects.LegList( + [base_objects.Leg({'id':21, 'state':False})] * 2 + + [base_objects.Leg({'id':21, 'state':True})] * nfinal), + 'model':self.base_model})) + return bool(amplitude.seed_forbidden_cubic_ids) + + threshold = madgraph.merge_quartic_min_legs + for nfinal in (2, 3, 4): + wanted = (2 + nfinal) >= threshold + self.assertEqual(seeded(nfinal, 'auto'), wanted) + # asking for it by name is unconditional, that being the way to + # get the merging on a small process + self.assertTrue(seeded(nfinal, 'speed')) + self.assertTrue(seeded(nfinal, 'slots')) + self.assertFalse(seeded(nfinal, False)) + def test_seed_inactive_by_default(self): """Nothing changes unless madgraph.merge_quartic_vertices is set""" From fbb5d2b5f94bef4a092575c3ec76d1de4617e20e Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Tue, 11 Aug 2026 17:00:08 +0200 Subject: [PATCH 37/39] recycle the AMP array, the way the wavefunctions already are AMP was declared COMPLEX*16 AMP(NGRAPHS) at the full diagram count in every mode, so seven gluons allocated 113 kB of it and speed left 432 entries written by nobody. get_amplitude_slots now does for AMP what reuse_outdated_wavefunctions does for W, and the enabling change is where the merges are written: they used to come out in one block at the end, which kept every source alive to the end, and each is now written as soon as both of its amplitudes exist, which frees the source. process mode AMP entries total per call g g > g g g g off 510 13.1 kB speed 316 12.9 kB -2% slots 106 7.1 kB -46% g g > 5 g off 7245 140.4 kB speed 5869 118.0 kB -16% slots 946 35.0 kB -75% slots reaches the floor and speed does not, and that is the diagram order rather than the allocator. Only (2n-5)!! amplitudes are read by the JAMPs, 945 at seven gluons, and the rest are merge sources which could share a handful of entries. speed emits every seed before its unrollings, so a source is born early and its target arrives late and nothing can be reclaimed in between. Reversing that puts each source beside its target, so slots lands one above the floor. That is worth a lot to the case slots exists for: it used to buy 23% of the wavefunction store, and now buys 75% of the whole per-thread working set. It buys no time -- 2247 -> 2260 us on speed and 2347 -> 2373 on slots at six gluons, both inside the 0.6% floor. The arrays were already cache resident at this size. This is a memory change, not a speed one. NGRAPHS only ever dimensioned AMP inside matrix.f so it becomes the entry count, with ngraphs.inc keeping the diagram count. The JAMPs go through map_color_amplitudes and AMP2 through get_amplitude_slot_map; AMP2 was the one worth checking, since multichannel reads individual amplitudes, and it reads only merge targets, which are the entries that stay put. Verified on a madevent output at six gluons: 316 written, 316 read, no entry read that is never written. |M|^2 unchanged on every row. 918 unit tests, one new, same two pre-existing failures. Co-Authored-By: Claude Opus 5 --- docs/gluon-quartic-plan.md | 61 +++++++++++++++ madgraph/core/helas_objects.py | 58 +++++++++++++++ madgraph/iolibs/export_v4.py | 53 +++++++++++-- madgraph/iolibs/helas_call_writers.py | 74 ++++++++++++++++++- .../core/test_diagram_generation.py | 35 +++++++++ 5 files changed, 271 insertions(+), 10 deletions(-) diff --git a/docs/gluon-quartic-plan.md b/docs/gluon-quartic-plan.md index 63ac4e89f8..857bf2eaaa 100644 --- a/docs/gluon-quartic-plan.md +++ b/docs/gluon-quartic-plan.md @@ -595,6 +595,67 @@ the 0.6% floor) and never negative, at an unchanged slot count. Above the threshold nothing changes: `auto` at six legs generates a byte-identical `matrix.f` to `speed`. +## Recycling the AMP array + +`reuse_outdated_wavefunctions` recycles the wavefunctions; the amplitudes were +not recycled at all. `AMP` was declared `COMPLEX*16 AMP(NGRAPHS)` at the full +diagram count in every mode, so seven gluons allocated 113 kB of it and +`speed` left 432 entries written by nobody. + +`HelasMatrixElement.get_amplitude_slots` now does for AMP what +`reuse_outdated_wavefunctions` does for W. The enabling change is *where the +merges are written*: they used to be emitted in one block at the very end, +which kept every source alive to the end, and each is now written as soon as +both of its amplitudes exist. Once `AMP(t) = AMP(t) + AMP(s)` has run, `s` is +free. + +| process | mode | AMP entries | AMP | W slots | W | total per call | +|---|---|---|---|---|---|---| +| `g g > g g g` | off | 45 | 0.7 kB | 12 | 1.2 kB | 1.9 kB | +| | auto | 16 | 0.2 kB | 12 | 1.2 kB | 1.5 kB (-24%) | +| | speed | 24 | 0.4 kB | 19 | 1.9 kB | 2.3 kB (+20%) | +| | slots | 16 | 0.2 kB | 12 | 1.2 kB | 1.5 kB (-24%) | +| `g g > g g g g` | off | 510 | 8.0 kB | 51 | 5.2 kB | 13.1 kB | +| | speed | 316 | 4.9 kB | 78 | 7.9 kB | 12.9 kB (-2%) | +| | slots | **106** | 1.7 kB | 54 | 5.5 kB | 7.1 kB (**-46%**) | +| `g g > t t~ g g` | off | 159 | 2.5 kB | 26 | 2.6 kB | 5.1 kB | +| | speed | 109 | 1.7 kB | 35 | 3.6 kB | 5.3 kB (+3%) | +| | slots | 106 | 1.7 kB | 29 | 2.9 kB | 4.6 kB (-10%) | +| `g g > 5 g` | off | 7245 | 113.2 kB | 268 | 27.2 kB | 140.4 kB | +| | speed | 5869 | 91.7 kB | 259 | 26.3 kB | 118.0 kB (-16%) | +| | slots | **946** | 14.8 kB | 199 | 20.2 kB | **35.0 kB (-75%)** | + +**`slots` reaches the floor and `speed` does not**, and the reason is the +diagram order rather than anything about the allocator. Only (2n-5)!! of the +amplitudes are read by the JAMPs -- 105 at six gluons, 945 at seven -- and +everything else is a merge source which could in principle share a handful of +entries. `speed` emits every seed before its unrollings, so a source is born +early and its target arrives late and the entry cannot be reclaimed in +between: 5869 rather than 945. Reversing that order puts each source next to +its target, so `slots` lands on 946 and 106, one above the floor. + +That changes the `slots` case rather a lot. It used to buy 23% of the +wavefunction store and cost 6% more arithmetic; it now buys **75% of the whole +per-call working set** at seven gluons, which is the number that matters on a +gpu, where this is per thread. + +**It buys no time.** Measured at `g g > g g g g`, minimum of five: `speed` +2247 -> 2260 us and `slots` 2347 -> 2373 us across the change, both inside the +0.6% floor and if anything marginally the wrong way -- the arrays were already +cache resident at this size, and the merges are now interleaved rather than +batched. This is a memory optimisation, not a speed one. + +`NGRAPHS` only ever dimensioned `AMP` inside `matrix.f`, so it simply becomes +the entry count; `ngraphs.inc` keeps the diagram count. Everything reading AMP +afterwards goes through the same map: the JAMPs through +`ProcessExporterFortran.map_color_amplitudes`, and AMP2 through +`get_amplitude_slot_map`. AMP2 was the one to check, since multichannel reads +individual amplitudes -- it reads only the merge *targets*, which are the +entries that stay put, so it is unaffected. Verified on a madevent output at +six gluons: 316 entries written, 316 read, none read that is never written. + +`|M|^2` is unchanged on every row. + ## The diagram order — measured, and worth a lot `reuse_outdated_wavefunctions` is a linear scan allocator over lifetimes taken diff --git a/madgraph/core/helas_objects.py b/madgraph/core/helas_objects.py index 4d975579eb..eaf4e649b0 100755 --- a/madgraph/core/helas_objects.py +++ b/madgraph/core/helas_objects.py @@ -4004,6 +4004,8 @@ def default_setup(self): self.quartic_current_sums = None # Slots the current sums were given by reuse_outdated_wavefunctions self.quartic_sum_me_ids = None + # Cache for get_amplitude_slots(), the recycled AMP array + self.amplitude_slots = None def filter(self, name, value): """Filter for valid diagram property values.""" @@ -6293,6 +6295,62 @@ def get_quartic_sum_me_ids(self): base = max(used or [0]) return [base + 1 + isum for isum in range(len(sums))] + def get_amplitude_slots(self): + """Recycle the AMP array the way reuse_outdated_wavefunctions recycles + the wavefunctions. + + Returns (slots, nslots, folds_at) where slots maps an amplitude number + onto its entry in AMP, nslots is how many entries that needs, and + folds_at maps a position in the emission order onto the merges to + write out just after it. + + An amplitude read by the JAMPs -- or by AMP2, which reads the same + ones, being the targets -- has to stay put until the end. A merge + source does not: once `AMP(t) = AMP(t) + AMP(s)` has run, its entry is + free. Writing each merge as soon as both of its amplitudes exist, + rather than all of them at the end, is what makes those entries worth + reclaiming. It only reclaims the gap between the two, so this is far + from the (2n-5)!! floor -- closing that would want the amplitudes + emitted in a different order, which is the wavefunction slot trade one + level down. + """ + + if self.amplitude_slots is not None: + return self.amplitude_slots + + folded = set(self.get_quartic_current_sums()[2]) + order = [amplitude.get('number') + for diagram in self.get('diagrams') + for amplitude in diagram.get('amplitudes') + if amplitude.get('number') not in folded] + position = dict((number, i) for i, number in enumerate(order)) + + # each merge is written as soon as both of its amplitudes are there + folds_at = {} + dies_at = {} + for source, (target, coeff) in \ + sorted(self.get_quartic_amplitude_merges().items()): + if source in folded or source not in position \ + or target not in position: + continue + at = max(position[source], position[target]) + folds_at.setdefault(at, []).append((target, source, coeff)) + dies_at.setdefault(at, []).append(source) + + slots, free, nslots = {}, [], 0 + for i, number in enumerate(order): + if free: + slots[number] = free.pop() + else: + nslots += 1 + slots[number] = nslots + # whatever this position's merges consume is free again after them + for source in dies_at.get(i, []): + free.append(slots[source]) + + self.amplitude_slots = (slots, nslots, folds_at) + return self.amplitude_slots + def compute_quartic_current_sums(self): """Work out the current sums, see get_quartic_current_sums.""" diff --git a/madgraph/iolibs/export_v4.py b/madgraph/iolibs/export_v4.py index 525478ac5c..e07ae7464e 100755 --- a/madgraph/iolibs/export_v4.py +++ b/madgraph/iolibs/export_v4.py @@ -2200,6 +2200,30 @@ def get_multi_channel_dictionary(diagrams, config_map): return config_to_diag_dict + @staticmethod + def get_amplitude_slot_map(matrix_element): + """{amplitude number: AMP entry} when the AMP array is recycled, else + None. See HelasMatrixElement.get_amplitude_slots -- the writer emits + each amplitude into its entry, so everything reading AMP afterwards + has to go through the same map.""" + + if not isinstance(matrix_element, helas_objects.HelasMatrixElement): + return None + if not matrix_element.get_quartic_amplitude_merges(): + return None + return matrix_element.get_amplitude_slots()[0] + + @classmethod + def map_color_amplitudes(cls, matrix_element, color_amplitudes): + """The colour amplitudes with the amplitude numbers replaced by the + AMP entries they were written into.""" + + slots = cls.get_amplitude_slot_map(matrix_element) + if slots is None: + return color_amplitudes + return [[(coeff, slots[number]) for coeff, number in col_amp] + for col_amp in color_amplitudes] + def get_amp2_lines(self, matrix_element, config_map = [], replace_dict=None): """Return the amp2(i) = sum(amp for diag(i))^2 lines""" @@ -2227,7 +2251,10 @@ def get_amp2_lines(self, matrix_element, config_map = [], replace_dict=None): line = "AMP2(%(num)d)=AMP2(%(num)d)+" % \ {"num": (config_to_diag_dict[config][0] + 1)} - amp = "+".join(["AMP(%(num)d)" % {"num": a.get('number')} for a in \ + slots = self.get_amplitude_slot_map(matrix_element) + amp = "+".join(["AMP(%(num)d)" % + {"num": slots[a.get('number')] if slots + else a.get('number')} for a in \ sum([diagrams[idiag].get('amplitudes') for \ idiag in config_to_diag_dict[config]], [])]) @@ -2323,7 +2350,8 @@ def get_JAMP_lines_split_order(self, col_amps, split_order_amps, error_msg="Malformed '%s' argument passed to the "+\ "get_JAMP_lines_split_order function: %s"%str(split_order_amps) if(isinstance(col_amps,helas_objects.HelasMatrixElement)): - color_amplitudes=col_amps.get_color_amplitudes() + color_amplitudes=self.map_color_amplitudes( + col_amps, col_amps.get_color_amplitudes()) elif(isinstance(col_amps,list)): if(col_amps and isinstance(col_amps[0],list)): color_amplitudes=col_amps @@ -2397,7 +2425,8 @@ def get_JAMP_lines(self, col_amps, JAMP_format="JAMP(%s)", AMP_format="AMP(%s)", # Let the user call get_JAMP_lines directly from a MatrixElement or from # the color amplitudes lists. if(isinstance(col_amps,helas_objects.HelasMatrixElement)): - color_amplitudes=col_amps.get_color_amplitudes() + color_amplitudes=self.map_color_amplitudes( + col_amps, col_amps.get_color_amplitudes()) elif(isinstance(col_amps,list)): if(col_amps and isinstance(col_amps[0],list)): color_amplitudes=col_amps @@ -4240,7 +4269,10 @@ def write_matrix_element_v4(self, writer, matrix_element, fortran_model, # Extract ngraphs ngraphs = matrix_element.get_number_of_amplitudes() - replace_dict['ngraphs'] = ngraphs + # NGRAPHS only dimensions AMP, and AMP is recycled + slots = self.get_amplitude_slot_map(matrix_element) + replace_dict['ngraphs'] = \ + matrix_element.get_amplitude_slots()[1] if slots else ngraphs # Extract nwavefuncs nwavefuncs = matrix_element.get_number_of_wavefunctions() @@ -4601,7 +4633,8 @@ def get_JAMP_lines(self, col_amps, JAMP_format="JAMP(%s)", AMP_format="AMP(%s)", error_msg="Malformed '%s' argument passed to the get_JAMP_lines" if(isinstance(col_amps,helas_objects.HelasMatrixElement)): - col_amps=col_amps.get_color_amplitudes() + col_amps=self.map_color_amplitudes( + col_amps, col_amps.get_color_amplitudes()) elif(isinstance(col_amps,list)): if(col_amps and isinstance(col_amps[0],list)): col_amps=col_amps @@ -5128,7 +5161,10 @@ def write_matrix_element_v4(self, writer, matrix_element, fortran_model,proc_id # Extract ngraphs ngraphs = matrix_element.get_number_of_amplitudes() - replace_dict['ngraphs'] = ngraphs + # NGRAPHS only dimensions AMP, and AMP is recycled + slots = self.get_amplitude_slot_map(matrix_element) + replace_dict['ngraphs'] = \ + matrix_element.get_amplitude_slots()[1] if slots else ngraphs # Extract nwavefuncs nwavefuncs = matrix_element.get_number_of_wavefunctions() @@ -6174,7 +6210,10 @@ def write_matrix_element_v4(self, writer, matrix_element, fortran_model, # Extract ngraphs ngraphs = matrix_element.get_number_of_amplitudes() - replace_dict['ngraphs'] = ngraphs + # NGRAPHS only dimensions AMP, and AMP is recycled + slots = self.get_amplitude_slot_map(matrix_element) + replace_dict['ngraphs'] = \ + matrix_element.get_amplitude_slots()[1] if slots else ngraphs # Extract ndiags ndiags = len(matrix_element.get('diagrams')) diff --git a/madgraph/iolibs/helas_call_writers.py b/madgraph/iolibs/helas_call_writers.py index d5637a3366..06f813f714 100755 --- a/madgraph/iolibs/helas_call_writers.py +++ b/madgraph/iolibs/helas_call_writers.py @@ -242,6 +242,12 @@ def get_matrix_element_calls(self, matrix_element): after.setdefault(max(cubic.get('number'), quartic.get('number')), []).append(i) + # The AMP array is recycled the same way, where the writer knows how + # to. A merge is written as soon as both of its amplitudes are there, + # which is what frees the source's entry, see get_amplitude_slots. + amp_slots = self.get_amplitude_slots(matrix_element) + position = [0] + res = [] written = set() for diagram in matrix_element.get('diagrams'): @@ -264,13 +270,49 @@ def get_matrix_element_calls(self, matrix_element): if amplitude.get('number') in folded: # summed into another amplitude through a current sum continue - res.append(self.get_amplitude_call_on_sums( - amplitude, uses.get(amplitude.get('number')), slots)) + res.append(self.get_amplitude_call_on_slot( + amplitude, uses.get(amplitude.get('number')), slots, + amp_slots)) + if amp_slots is not None: + res.extend(self.get_amplitude_merge_lines_at( + amp_slots, position[0])) + position[0] += 1 - res.extend(self.get_amplitude_merge_lines(matrix_element)) + if amp_slots is None: + res.extend(self.get_amplitude_merge_lines(matrix_element)) return res + def get_amplitude_slots(self, matrix_element): + """The recycled AMP array, or None to leave AMP indexed by amplitude + number. Only the Fortran writer has an AMP array to recycle.""" + + return None + + def get_amplitude_call_on_slot(self, amplitude, substitution, slots, + amp_slots): + """The amplitude call, written into its recycled AMP entry. + + The slot is swapped onto the amplitude's number and put straight back, + the same way get_amplitude_call_on_sums does it for the mothers: the + call is formatted from `out`, which is that number.""" + + if amp_slots is None: + return self.get_amplitude_call_on_sums(amplitude, substitution, + slots) + number = amplitude.get('number') + amplitude.set('number', amp_slots[0][number]) + try: + return self.get_amplitude_call_on_sums(amplitude, substitution, + slots) + finally: + amplitude.set('number', number) + + def get_amplitude_merge_lines_at(self, amp_slots, position): + """The merges due just after this amplitude. Fortran only.""" + + return [] + def get_quartic_current_sums(self, matrix_element): """The current sums to write out. Only the Fortran writer knows how to emit one, see FortranUFOHelasCallWriter.""" @@ -1127,6 +1169,32 @@ def get_amplitude_merge_lines(self, matrix_element): (target, target, float(coeff), source)) return res + def get_amplitude_slots(self, matrix_element): + """The recycled AMP array, see + HelasMatrixElement.get_amplitude_slots.""" + + if not matrix_element.get_quartic_amplitude_merges(): + return None + return matrix_element.get_amplitude_slots() + + def get_amplitude_merge_lines_at(self, amp_slots, position): + """The merges whose two amplitudes are both there as of this + position, written into the slots they were given.""" + + slots, nslots, folds_at = amp_slots + res = [] + for target, source, coeff in folds_at.get(position, []): + args = (slots[target], slots[target], slots[source]) + if coeff == 1: + res.append('AMP(%d) = AMP(%d) + AMP(%d)' % args) + elif coeff == -1: + res.append('AMP(%d) = AMP(%d) - AMP(%d)' % args) + else: + res.append('AMP(%d) = AMP(%d) + (%.15e)*AMP(%d)' % + (slots[target], slots[target], float(coeff), + slots[source])) + return res + def get_quartic_current_sums(self, matrix_element): """The current sums, see HelasMatrixElement.get_quartic_current_sums""" diff --git a/tests/unit_tests/core/test_diagram_generation.py b/tests/unit_tests/core/test_diagram_generation.py index de080e25cf..954027b885 100755 --- a/tests/unit_tests/core/test_diagram_generation.py +++ b/tests/unit_tests/core/test_diagram_generation.py @@ -4385,6 +4385,41 @@ def seeded(nfinal, mode): self.assertTrue(seeded(nfinal, 'slots')) self.assertFalse(seeded(nfinal, False)) + def test_amplitude_slots(self): + """The AMP array is recycled: an amplitude summed into another frees + its entry, and the entries have to be reusable without two live + amplitudes ever sharing one""" + + import madgraph.core.helas_objects as helas_objects + + madgraph.merge_quartic_vertices = 'speed' + amplitude = diagram_generation.Amplitude(base_objects.Process( + {'legs':base_objects.LegList( + [base_objects.Leg({'id':21, 'state':False})] * 2 + + [base_objects.Leg({'id':21, 'state':True})] * 4), + 'model':self.base_model})) + element = helas_objects.HelasMatrixElement(amplitude) + slots, nslots, folds_at = element.get_amplitude_slots() + + self.assertEqual(element.get_number_of_amplitudes(), 510) + self.assertTrue(nslots < 510) + self.assertEqual(max(slots.values()), nslots) + self.assertEqual(min(slots.values()), 1) + + # replay the emission and check no entry is written while it still + # holds something with a reader to come + folded = set(element.get_quartic_current_sums()[2]) + order = [a.get('number') for d in element.get('diagrams') + for a in d.get('amplitudes') if a.get('number') not in folded] + self.assertEqual(len(order), len(slots)) + live = {} + for i, number in enumerate(order): + self.assertNotIn(slots[number], live) + live[slots[number]] = number + for target, source, coeff in folds_at.get(i, []): + self.assertIn(slots[source], live) + del live[slots[source]] + def test_seed_inactive_by_default(self): """Nothing changes unless madgraph.merge_quartic_vertices is set""" From e23e413a146644071181ca207ef5f5f31e09c9c7 Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Tue, 11 Aug 2026 17:20:12 +0200 Subject: [PATCH 38/39] re-measure the sweep now that the AMP array is recycled The full sweep tables were taken before AMP was recycled, so their AMP columns described an array sized at the full diagram count, and the paragraph reading them off said the AMP array never shrinks. Both re-measured on the current code, all 24 builds again, timings the minimum of five as before. The AMP column is now the entry count rather than the amplitude count, and the two are worth telling apart -- at seven gluons slots runs 7245 amplitude calls through 946 entries. g g > 5 g generate matrix.o W slots AMP entries per call off 35.2 s 5.8 MB 268 7245 141.0 ms speed 16.6 s 3.4 MB 259 5869 132.8 ms +6% slots 18.4 s 3.4 MB 199 946 134.3 ms +5% Two cells were re-measured on their own because a single run had caught noise: g g > t t~ g generation read 5.3 s against 1.8 s over three runs, and the 0.6% floor is now 4.000 against 3.988 us on the byte-identical pair. Co-Authored-By: Claude Opus 5 --- docs/gluon-quartic-plan.md | 77 +++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 38 deletions(-) diff --git a/docs/gluon-quartic-plan.md b/docs/gluon-quartic-plan.md index 857bf2eaaa..668feaf505 100644 --- a/docs/gluon-quartic-plan.md +++ b/docs/gluon-quartic-plan.md @@ -496,8 +496,8 @@ Timings are the minimum of five runs of the shipped `check` driver looping `SMATRIX` on a fixed phase space point; the minimum matters, because a single run carries about 3% of noise and most of the effects here are smaller than that. The floor of the method is 0.6%, measured on `g g > t t~`, where `off` -and `speed` produce a byte-identical `matrix.f` and still time 3.975 against -4.000 us. `|M|^2` agrees to 8.5e-15 or better on every row. +and `speed` produce a byte-identical `matrix.f` and still time 4.000 against +3.988 us. `|M|^2` agrees to 8.5e-15 or better on every row. *slots* is `NWAVEFUNCS`, the length of the wavefunction array, `TYPE(ALOHA) W(NWAVEFUNCS)` -- not the number of wavefunctions computed, since @@ -508,45 +508,46 @@ run (898 wavefunction calls live in 268 slots at seven gluons). One entry is **`g g > N g`** -| process | mode | generate | matrix.f | matrix.o | slots | W array | amps decl | amps computed | AMP array | per call | speed | +| process | mode | generate | matrix.f | matrix.o | W slots | W array | AMP entries | amps computed | AMP array | per call | speed | |---|---|---|---|---|---|---|---|---|---|---|---| | g g > 2g | off | 1.8 s | 27 kB | 16 kB | 5 | 0.5 kB | 6 | 6 | 0.1 kB | 5.48 us | - | -| | speed | 1.6 s | 27 kB | 17 kB | 5 | 0.5 kB | 6 | 6 | 0.1 kB | 5.52 us | -1% | -| | slots | 1.8 s | 27 kB | 17 kB | 5 | 0.5 kB | 6 | 6 | 0.1 kB | 5.55 us | -1% | -| g g > 3g | off | 1.9 s | 40 kB | 28 kB | 12 | 1.2 kB | 45 | 45 | 0.7 kB | 86.75 us | - | -| | speed | 1.8 s | 39 kB | 29 kB | 19 | 1.9 kB | 45 | 38 | 0.7 kB | 87.25 us | -1% | -| | slots | 1.9 s | 40 kB | 29 kB | 12 | 1.2 kB | 45 | 45 | 0.7 kB | 93.25 us | -7% | -| g g > 4g | off | 3.0 s | 181 kB | 141 kB | 51 | 5.2 kB | 510 | 510 | 8.0 kB | 2.37 ms | - | -| | speed | 2.4 s | 166 kB | 147 kB | 78 | 7.9 kB | 510 | 450 | 8.0 kB | 2.24 ms | +5% | -| | slots | 2.4 s | 168 kB | 153 kB | 54 | 5.5 kB | 510 | 510 | 8.0 kB | 2.36 ms | +0% | -| g g > 5g | off | 37.1 s | 3.3 MB | 5.8 MB | 268 | 27.2 kB | 7245 | 7245 | 113.2 kB | 140.75 ms | - | -| | speed | 19.4 s | 2.5 MB | 3.6 MB | 259 | 26.3 kB | 7245 | 6813 | 113.2 kB | 133.25 ms | +5% | -| | slots | 18.3 s | 2.6 MB | 3.5 MB | 199 | 20.2 kB | 7245 | 7245 | 113.2 kB | 135.50 ms | +4% | +| | speed | 1.5 s | 27 kB | 17 kB | 5 | 0.5 kB | 4 | 6 | 0.1 kB | 5.52 us | -1% | +| | slots | 1.6 s | 27 kB | 17 kB | 5 | 0.5 kB | 4 | 6 | 0.1 kB | 5.55 us | -1% | +| g g > 3g | off | 2.1 s | 40 kB | 28 kB | 12 | 1.2 kB | 45 | 45 | 0.7 kB | 87.50 us | - | +| | speed | 1.8 s | 39 kB | 29 kB | 19 | 1.9 kB | 24 | 38 | 0.4 kB | 90.25 us | -3% | +| | slots | 2.4 s | 40 kB | 29 kB | 12 | 1.2 kB | 16 | 45 | 0.2 kB | 93.00 us | -6% | +| g g > 4g | off | 2.8 s | 181 kB | 141 kB | 51 | 5.2 kB | 510 | 510 | 8.0 kB | 2.37 ms | - | +| | speed | 2.4 s | 165 kB | 146 kB | 78 | 7.9 kB | 316 | 450 | 4.9 kB | 2.29 ms | +4% | +| | slots | 2.4 s | 168 kB | 152 kB | 54 | 5.5 kB | 106 | 510 | 1.7 kB | 2.41 ms | -2% | +| g g > 5g | off | 35.2 s | 3.3 MB | 5.8 MB | 268 | 27.2 kB | 7245 | 7245 | 113.2 kB | 141.00 ms | - | +| | speed | 16.6 s | 2.5 MB | 3.4 MB | 259 | 26.3 kB | 5869 | 6813 | 91.7 kB | 132.75 ms | +6% | +| | slots | 18.4 s | 2.5 MB | 3.4 MB | 199 | 20.2 kB | 946 | 7245 | 14.8 kB | 134.25 ms | +5% | **`g g > t t~ N g`** -| process | mode | generate | matrix.f | matrix.o | slots | W array | amps decl | amps computed | AMP array | per call | speed | +| process | mode | generate | matrix.f | matrix.o | W slots | W array | AMP entries | amps computed | AMP array | per call | speed | |---|---|---|---|---|---|---|---|---|---|---|---| -| g g > t t~ | off | 1.7 s | 26 kB | 16 kB | 5 | 0.5 kB | 3 | 3 | 0.0 kB | 4.00 us | - | -| | speed | 1.6 s | 26 kB | 16 kB | 5 | 0.5 kB | 3 | 3 | 0.0 kB | 4.00 us | +0% | -| | slots | 1.6 s | 26 kB | 16 kB | 5 | 0.5 kB | 3 | 3 | 0.0 kB | 4.10 us | -2% | -| g g > t t~ g | off | 2.1 s | 31 kB | 20 kB | 12 | 1.2 kB | 18 | 18 | 0.3 kB | 30.25 us | - | -| | speed | 1.9 s | 31 kB | 20 kB | 12 | 1.2 kB | 18 | 15 | 0.3 kB | 29.92 us | +1% | -| | slots | 1.8 s | 31 kB | 21 kB | 12 | 1.2 kB | 18 | 18 | 0.3 kB | 30.50 us | -1% | -| g g > t t~ 2g | off | 2.4 s | 68 kB | 51 kB | 26 | 2.6 kB | 159 | 159 | 2.5 kB | 377.00 us | - | -| | speed | 2.3 s | 65 kB | 49 kB | 35 | 3.6 kB | 159 | 126 | 2.5 kB | 350.00 us | +7% | -| | slots | 2.3 s | 66 kB | 53 kB | 29 | 2.9 kB | 159 | 159 | 2.5 kB | 390.00 us | -3% | -| g g > t t~ 3g | off | 6.4 s | 576 kB | 479 kB | 121 | 12.3 kB | 1890 | 1890 | 29.5 kB | 9.60 ms | - | -| | speed | 5.3 s | 473 kB | 414 kB | 213 | 21.6 kB | 1890 | 1551 | 29.5 kB | 8.87 ms | +8% | -| | slots | 5.2 s | 487 kB | 460 kB | 141 | 14.3 kB | 1890 | 1890 | 29.5 kB | 9.73 ms | -1% | +| g g > t t~ | off | 1.5 s | 26 kB | 16 kB | 5 | 0.5 kB | 3 | 3 | 0.0 kB | 4.00 us | - | +| | speed | 1.5 s | 26 kB | 16 kB | 5 | 0.5 kB | 3 | 3 | 0.0 kB | 3.99 us | +0% | +| | slots | 2.0 s | 26 kB | 16 kB | 5 | 0.5 kB | 3 | 3 | 0.0 kB | 4.09 us | -2% | +| g g > t t~ g | off | 1.8 s | 31 kB | 20 kB | 12 | 1.2 kB | 18 | 18 | 0.3 kB | 30.00 us | - | +| | speed | 1.6 s | 31 kB | 20 kB | 12 | 1.2 kB | 15 | 15 | 0.2 kB | 29.58 us | +1% | +| | slots | 1.7 s | 31 kB | 21 kB | 12 | 1.2 kB | 15 | 18 | 0.2 kB | 30.33 us | -1% | +| g g > t t~ 2g | off | 2.6 s | 68 kB | 51 kB | 26 | 2.6 kB | 159 | 159 | 2.5 kB | 377.00 us | - | +| | speed | 2.4 s | 65 kB | 49 kB | 35 | 3.6 kB | 109 | 126 | 1.7 kB | 343.00 us | +9% | +| | slots | 2.4 s | 66 kB | 53 kB | 29 | 2.9 kB | 106 | 159 | 1.7 kB | 391.00 us | -4% | +| g g > t t~ 3g | off | 6.2 s | 576 kB | 479 kB | 121 | 12.3 kB | 1890 | 1890 | 29.5 kB | 9.63 ms | - | +| | speed | 4.9 s | 463 kB | 408 kB | 213 | 21.6 kB | 1159 | 1551 | 18.1 kB | 8.97 ms | +7% | +| | slots | 5.0 s | 493 kB | 466 kB | 141 | 14.3 kB | 946 | 1890 | 14.8 kB | 9.93 ms | -3% | Two things worth reading off the amplitude columns. -**The AMP array never shrinks.** It is declared `COMPLEX*16 AMP(NGRAPHS)` at -the full diagram count whatever the mode, so all three builds allocate 113 kB -at seven gluons and `speed` leaves 432 entries written by nobody. The -amplitude memory is identical everywhere; only the number computed moves. So -the optimisation saves memory only in the W array, and only in `slots` mode. +**The AMP array is recycled too, and it is where `slots` wins.** It used to be +declared at the full diagram count in every mode -- 113 kB at seven gluons, +with `speed` leaving 432 entries written by nobody -- which is what prompted +"Recycling the AMP array" below. Now `slots` runs 7245 amplitude calls through +946 entries at seven gluons, 14.8 kB rather than 113.2, while `speed` only +reaches 5869 because of the order it emits them in. **`slots` mode computes every amplitude** -- `amps computed` equals `amps decl` on all eight of its rows. With no current sums nothing is skipped, so it @@ -558,13 +559,13 @@ memory. `speed` is the opposite, skipping amplitudes outright (450 of 510, slots -- 121 to 213 at `g g > t t~ 3g`. **What it is actually good for.** Generation time and code size, more than -speed. `g g > 5 g` generates in 19.4 s rather than 37.1 s, a 48% cut and +speed. `g g > 5 g` generates in 16.6 s rather than 35.2 s, a 53% cut and reproducible: 385 seed diagrams unrolled is cheaper than 2485 generated. Its -`matrix.o` goes 5.8 MB to 3.6 MB. Runtime is a steady 5-8% above six particles -and nothing at all below, and the `t t~` series gains more than the pure gluon -one at equal particle count, +8% at `t t~ 3g` against +5% at `4g`. Peak RSS is -flat except at seven gluons, because the wavefunction store is a stack frame -and the code image dominates. +`matrix.o` goes 5.8 MB to 3.4 MB and its `matrix.f` 3.3 MB to 2.5 MB. Runtime +is 4-9% above six particles and nothing at all below, and the `t t~` series +gains more than the pure gluon one at equal particle count, +9% at +`t t~ 2g` against +4% at `4g`. Peak RSS is flat except at seven gluons, +because the wavefunction store is a stack frame and the code image dominates. ## The multiplicity gate From 78a801f60435116856c79fb20a1951153bee101a Mon Sep 17 00:00:00 2001 From: Olivier Mattelaer Date: Tue, 11 Aug 2026 18:15:23 +0200 Subject: [PATCH 39/39] check the sweep against a process with little to merge Both series in the sweep are gluon-rich, so u u~ > z g g g g was measured as a control: seven legs like g g > t t~ 3g, but with a Z and a quark line, so most of its diagrams have no four gluon vertex at all. It is the weakest case measured, and predictably so. In slots mode the AMP entry count turns out to be exactly total amplitudes minus merge sources, to within one, on every process measured: amplitudes merge sources AMP in slots saving g g > 5 g 7245 6300 (87%) 946 -87% g g > g g g g 510 405 (79%) 106 -79% g g > t t~ 3g 1890 945 (50%) 946 -50% u u~ > z 4g 516 132 (26%) 384 -26% So the payoff tracks the quartic fraction. Runtime follows at +4% rather than +7 to +9%, and the working set at -8% rather than -30 or -75%. It is also the one process where slots does not reduce the wavefunctions either, 84 against off's 76, which breaks the pattern from the gluon-rich processes where reversing the order always recovered them. There slots is the worst of the three: 5% slower than off and larger in W, for an AMP count it barely wins over speed. speed still behaves, +4% with generation down 21%, which is what the auto gate picks at seven legs anyway. Co-Authored-By: Claude Opus 5 --- docs/gluon-quartic-plan.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/docs/gluon-quartic-plan.md b/docs/gluon-quartic-plan.md index 668feaf505..2a8cb6d1cb 100644 --- a/docs/gluon-quartic-plan.md +++ b/docs/gluon-quartic-plan.md @@ -567,6 +567,44 @@ gains more than the pure gluon one at equal particle count, +9% at `t t~ 2g` against +4% at `4g`. Peak RSS is flat except at seven gluons, because the wavefunction store is a stack frame and the code image dominates. +**How far it generalises.** Both series above are gluon-rich, so a third +process was measured as a check: `u u~ > z g g g g`, seven legs like +`g g > t t~ 3g` but with a Z and a quark line, so most of its diagrams have no +four gluon vertex at all. (`q` is not a defined multiparticle, hence `u u~`.) + +| process | mode | generate | matrix.f | matrix.o | W slots | AMP entries | amps computed | per call | speed | total/call | +|---|---|---|---|---|---|---|---|---|---|---| +| `g g > t t~ 3g` | off | 6.2 s | 576 kB | 479 kB | 121 | 1890 | 1890 | 9.63 ms | - | 41.8 kB | +| | speed | 4.9 s | 463 kB | 408 kB | 213 | 1159 | 1551 | 8.97 ms | +7% | 39.7 kB (-5%) | +| | slots | 5.0 s | 493 kB | 466 kB | 141 | 946 | 1890 | 9.93 ms | -3% | **29.1 kB (-30%)** | +| `u u~ > z 4g` | off | 2.9 s | 135 kB | 115 kB | 76 | 516 | 516 | 1.58 ms | - | 15.8 kB | +| | speed | 2.3 s | 127 kB | 110 kB | 85 | 391 | 450 | 1.51 ms | +4% | 14.7 kB (-7%) | +| | slots | 2.3 s | 132 kB | 117 kB | 84 | 384 | 516 | 1.65 ms | -5% | 14.5 kB (-8%) | + +**The payoff tracks the quartic fraction, exactly.** In `slots` mode the AMP +entry count is `total amplitudes - merge sources`, to within one, on every +process measured: + +| | amplitudes | merge sources | AMP in `slots` | saving | +|---|---|---|---|---| +| `g g > 5 g` | 7245 | 6300 (87%) | 946 | -87% | +| `g g > g g g g` | 510 | 405 (79%) | 106 | -79% | +| `g g > t t~ 3g` | 1890 | 945 (50%) | 946 | -50% | +| `u u~ > z 4g` | 516 | 132 (**26%**) | 384 | -26% | + +So `u u~ > z 4g` is the weakest case measured, and predictably: there is +simply little to merge. Runtime follows at +4% rather than +7 to +9%, and the +working set at -8% rather than -30 or -75%. + +It is also the one process where **`slots` does not reduce the wavefunctions +either** -- 84 against off's 76, worse -- which breaks the pattern from the +gluon-rich processes, where reversing the order always recovered them. On this +topology `slots` is the worst of the three: 5% slower than off and larger in +W, for an AMP count it barely wins over `speed`, 384 against 391. `speed` +still behaves, +4% with generation down 21% and a smaller source and object, +which is also what the `auto` gate picks at seven legs. + + ## The multiplicity gate The sweep says the full merging turns over at six external legs, and the same