Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat(grcc): implment qgraf-compatible keywords in FORM
These pass a large number of comparisons with qgraf, using
@tueda's "qgraf.frm" comparison procedures.
  • Loading branch information
jodavies authored and tueda committed Dec 9, 2025
commit ab36b49f50fd5c783fcc5a890305da0420ea4c84
142 changes: 82 additions & 60 deletions sources/diawrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ void ProcessDiagram(EGraph *eg, void *ti)
//
// Now get the nodes
//
if ( ( info->flags & NONODES ) == 0 ) {
if ( ( info->flags & WITHOUTNODES ) == 0 ) {
for ( i = 0; i < eg->nNodes; i++ ) {
//
// node_(number,coupling,particle_1(momentum_1),...,particle_n(momentum_n))
Expand Down Expand Up @@ -395,7 +395,7 @@ void ProcessDiagram(EGraph *eg, void *ti)
startfill[1] = fill-startfill;
}
}
if ( ( info->flags & WITHONEPI ) == WITHONEPI ) {
if ( ( info->flags & WITHONEPISETS ) == WITHONEPISETS ) {
for ( i = 0; i < eg->econn->nopic; i++ ) {
startfill = fill;
*fill++ = ONEPI;
Expand Down Expand Up @@ -452,8 +452,6 @@ void ProcessDiagram(EGraph *eg, void *ti)
*newterm = fill - newterm;
AT.WorkPointer = fill;

// MesPrint("<> %a",newterm[0],newterm);

Generator(BHEAD newterm,info->level);
AT.WorkPointer = oldworkpointer;
}
Expand All @@ -479,6 +477,9 @@ Bool ProcessTopology(EGraph *eg, void *ti)
// return False; skip diagram generation (when asked for).
//
TERMINFO *info = (TERMINFO *)ti;

// This seems to work properly. It was disabled before.
#define WITHEARLYVETO
#ifdef WITHEARLYVETO
if ( ( ( info->flags & CHECKEXTERN ) == CHECKEXTERN ) && info->currentMODEL != NULL ) {
int i, j;
Expand All @@ -500,6 +501,7 @@ Bool ProcessTopology(EGraph *eg, void *ti)
}
}
#endif

if ( ( info->flags & TOPOLOGIESONLY ) == 0 ) {
info->numtopo++;
return True;
Expand Down Expand Up @@ -664,7 +666,7 @@ Bool ProcessTopology(EGraph *eg, void *ti)
// startfill[1] = fill-startfill;
// }
}
if ( ( info->flags & WITHONEPI ) == WITHONEPI ) {
if ( ( info->flags & WITHONEPISETS ) == WITHONEPISETS ) {
for ( i = 0; i < eg->econn->nopic; i++ ) {
startfill = fill;
*fill++ = ONEPI;
Expand Down Expand Up @@ -718,15 +720,39 @@ Bool ProcessTopology(EGraph *eg, void *ti)
*newterm = fill - newterm;
AT.WorkPointer = fill;

//MesPrint("<> %a",*newterm,newterm);

Generator(BHEAD newterm,info->level);
AT.WorkPointer = oldworkpointer;
info->numtopo++;
return False;
}

// #] ProcessTopology :
// #[ SetDualOpts :
void SetDualOpts(int *opt, const WORD num, const int key, const char* key_name,
const int dual, const char* dual_name, const int val, const int dval) {

if ( ( num & key ) == key ) {
if ( ( num & dual ) == dual ) {
MLOCK(ErrorMessageLock);
MesPrint("&Conflicting diagram filters: %s and %s.", key_name, dual_name);
MUNLOCK(ErrorMessageLock);
Terminate(-1);
}
else {
*opt = val;
}
}
else {
if ( ( num & dual ) == dual ) {
*opt = dval;
}
else {
// The default value is always 0.
*opt = 0;
}
}
}
// #] SetDualOpts :
// #[ GenDiagrams :

int GenDiagrams(PHEAD WORD *term, WORD level)
Expand Down Expand Up @@ -780,48 +806,46 @@ int GenDiagrams(PHEAD WORD *term, WORD level)

opt->setOutAG(ProcessDiagram, &info);
opt->setOutMG(ProcessTopology, &info);
// opt->setEndMG(fendMG, &info);

opt->values[GRCC_OPT_1PI] = ( optionnumber & ONEPARTICLEIRREDUCIBLE ) == ONEPARTICLEIRREDUCIBLE;
opt->values[GRCC_OPT_NoTadpole] = ( optionnumber & NOTADPOLES ) == NOTADPOLES;
//
// Next are snails:
//
opt->values[GRCC_OPT_No1PtBlock] = ( optionnumber & NOTADPOLES ) == NOTADPOLES;
//
if ( ( optionnumber & WITHINSERTIONS ) == WITHINSERTIONS ) {
opt->values[GRCC_OPT_No2PtL1PI] = True;
opt->values[GRCC_OPT_NoAdj2PtV] = True;
opt->values[GRCC_OPT_No2PtL1PI] = True;
}
else {
opt->values[GRCC_OPT_NoAdj2PtV] = True;
}
opt->values[GRCC_OPT_SymmInitial] = ( optionnumber & WITHSYMMETRIZE ) == WITHSYMMETRIZE;
opt->values[GRCC_OPT_SymmFinal] = ( optionnumber & WITHSYMMETRIZE ) == WITHSYMMETRIZE;

// opt->values[GRCC_OPT_Block] = ( optionnumber & WITHBLOCKS ) == WITHBLOCKS;
opt->values[GRCC_OPT_SymmInitial] = ( optionnumber & WITHSYMMETRIZEI ) == WITHSYMMETRIZEI;
opt->values[GRCC_OPT_SymmFinal] = ( optionnumber & WITHSYMMETRIZEF ) == WITHSYMMETRIZEF;

// WITHBLOCKS controls output formatting. We could introduce an extra filtering option
// corresponding to GRCC_OPT_Block, which is somewhat like Qgraf "onevi" but not quite
// the same currently.
//opt->values[GRCC_OPT_Block] = ;

// Now the "qgraf-compatible filtering options":
int qgopt[GRCC_QGRAF_OPT_Size];
SetDualOpts(&qgopt[GRCC_QGRAF_OPT_ONEPI], optionnumber,ONEPARTI, "ONEPI_", ONEPARTR, "ONEPR_", 1,-1);
SetDualOpts(&qgopt[GRCC_QGRAF_OPT_ONSHELL], optionnumber,ONSHELL, "ONSHELL_", OFFSHELL, "OFFSHELL_", 1,-1);
SetDualOpts(&qgopt[GRCC_QGRAF_OPT_NOSIGMA], optionnumber,NOSIGMA, "NOSIGMA_", SIGMA, "SIGMA_", 1,-1);
SetDualOpts(&qgopt[GRCC_QGRAF_OPT_NOSNAIL], optionnumber,NOSNAIL, "NOSNAIL_", SNAIL, "SNAIL_", 1,-1);
SetDualOpts(&qgopt[GRCC_QGRAF_OPT_NOTADPOLE],optionnumber,NOTADPOLE,"NOTADPOLE_",TADPOLE , "TADPOLE_", 1,-1);
SetDualOpts(&qgopt[GRCC_QGRAF_OPT_SIMPLE], optionnumber,SIMPLE, "SIMPLE_", NOTSIMPLE,"NOTSIMPLE_",1,-1);
SetDualOpts(&qgopt[GRCC_QGRAF_OPT_BIPART], optionnumber,BIPART, "BIPART_", NONBIPART,"NONBIPART_",1,-1);
SetDualOpts(&qgopt[GRCC_QGRAF_OPT_CYCLI], optionnumber,CYCLI, "CYCLI_", CYCLR, "CYCLR_", 1,-1);
SetDualOpts(&qgopt[GRCC_QGRAF_OPT_FLOOP], optionnumber,FLOOP, "FLOOP_", NOTFLOOP, "NOTFLOOP_", 1,-1);
// Now set the options internally:
opt->setQGrafOpt(qgopt);

opt->setOutputF(False,"");
opt->setOutputP(False,"");
opt->printLevel(babble);

// opt->values[GRCC_OPT_Step] = GRCC_AGraph;

// Load the various arrays.

ninitl = Sets[inset].last - Sets[inset].first;
for ( i = 0; i < ninitl; i++ ) {
x = SetElements[Sets[inset].first+i];
initlPart[i] = ConvertParticle(model,x);
ninitl = Sets[inset].last - Sets[inset].first;
for ( i = 0; i < ninitl; i++ ) {
x = SetElements[Sets[inset].first+i];
initlPart[i] = ConvertParticle(model,x);
info.legcouple[i] = m->vertices[numParticle(m,x)]->couplings;
}
nfinal = Sets[outset].last - Sets[outset].first;
for ( i = 0; i < nfinal; i++ ) {
x = SetElements[Sets[outset].first+i];
finalPart[i] = ConvertParticle(model,x);
}
nfinal = Sets[outset].last - Sets[outset].first;
for ( i = 0; i < nfinal; i++ ) {
x = SetElements[Sets[outset].first+i];
finalPart[i] = ConvertParticle(model,x);
info.legcouple[i+ninitl] = m->vertices[numParticle(m,x)]->couplings;
}
}
info.numextern = ninitl + nfinal;
for ( i = 2; i <= MAXLEGS; i++ ) {
if ( m->legcouple[i] == 1 ) {
Expand Down Expand Up @@ -850,16 +874,14 @@ Go_on:;

if ( ( info.flags & TOPOLOGIESONLY ) == 0 ) {
while ( DistrN(nc,cpl,m->ncouplings,scratch) ) {
proc = new Process(pid, model, opt,
ninitl, initlPart, nfinal, finalPart, cpl);
proc = new Process(pid, model, opt, ninitl, initlPart, nfinal, finalPart, cpl);
delete proc;
info.numtopo = 1;
}
}
else {
cpl[0] = nc;
proc = new Process(pid, model, opt,
ninitl, initlPart, nfinal, finalPart, cpl);
proc = new Process(pid, model, opt, ninitl, initlPart, nfinal, finalPart, cpl);
delete proc;
}
M_free(scratch,"DistrN");
Expand Down Expand Up @@ -892,8 +914,7 @@ Go_on:;
/*
And now the generation:
*/
proc = new Process(pid, model, opt,
ninitl, initlPart, nfinal, finalPart, cpl);
proc = new Process(pid, model, opt, ninitl, initlPart, nfinal, finalPart, cpl);
opt->end();
delete proc;
delete opt;
Expand Down Expand Up @@ -1000,22 +1021,23 @@ int GenTopologies(PHEAD WORD *term, WORD level)

info.flags |= TOPOLOGIESONLY; // this is the topologies_ function after all.
if ( t1 < tstop && t1[0] == -SNUMBER ) {
if ( ( t1[1] & NONODES ) == NONODES ) info.flags |= NONODES;
if ( ( t1[1] & WITHOUTNODES ) == WITHOUTNODES ) info.flags |= WITHOUTNODES;
if ( ( t1[1] & WITHEDGES ) == WITHEDGES ) info.flags |= WITHEDGES;
if ( ( t1[1] & WITHBLOCKS ) == WITHBLOCKS ) info.flags |= WITHBLOCKS;
if ( ( t1[1] & WITHONEPI ) == WITHONEPI ) info.flags |= WITHONEPI;
opt->values[GRCC_OPT_1PI] = ( t1[1] & ONEPARTICLEIRREDUCIBLE ) == ONEPARTICLEIRREDUCIBLE;
// opt->values[GRCC_OPT_NoTadpole] = ( t1[1] & NOTADPOLES ) == NOTADPOLES;
opt->values[GRCC_OPT_NoTadpole] = ( t1[1] & NOSNAILS ) == NOSNAILS;
opt->values[GRCC_OPT_No1PtBlock] = ( t1[1] & NOTADPOLES ) == NOTADPOLES;
opt->values[GRCC_OPT_NoExtSelf] = ( t1[1] & NOEXTSELF ) == NOEXTSELF;

if ( ( t1[1] & WITHINSERTIONS ) == WITHINSERTIONS ) {
opt->values[GRCC_OPT_No2PtL1PI] = True;
opt->values[GRCC_OPT_NoAdj2PtV] = True;
opt->values[GRCC_OPT_No2PtL1PI] = True;
}
opt->values[GRCC_OPT_SymmInitial] = ( t1[1] & WITHSYMMETRIZE ) == WITHSYMMETRIZE;
if ( ( t1[1] & WITHONEPISETS ) == WITHONEPISETS ) info.flags |= WITHONEPISETS;
opt->values[GRCC_OPT_1PI] = ( t1[1] & ONEPARTI ) == ONEPARTI;
// opt->values[GRCC_OPT_NoTadpole] = ( t1[1] & NOTADPOLE ) == NOTADPOLE;
opt->values[GRCC_OPT_NoTadpole] = ( t1[1] & NOSNAIL ) == NOSNAIL;
opt->values[GRCC_OPT_No1PtBlock] = ( t1[1] & NOTADPOLE ) == NOTADPOLE;
// opt->values[GRCC_OPT_NoExtSelf] = ( t1[1] & NOEXTSELF ) == NOEXTSELF;

// if ( ( t1[1] & WITHINSERTIONS ) == WITHINSERTIONS ) {
// opt->values[GRCC_OPT_No2PtL1PI] = True;
// opt->values[GRCC_OPT_NoAdj2PtV] = True;
// opt->values[GRCC_OPT_No2PtL1PI] = True;
// }
opt->values[GRCC_OPT_SymmInitial] = ( t1[1] & WITHSYMMETRIZEI ) == WITHSYMMETRIZEI;
opt->values[GRCC_OPT_SymmFinal] = ( t1[1] & WITHSYMMETRIZEF ) == WITHSYMMETRIZEF;
}

info.numdia = 0;
Expand Down
44 changes: 32 additions & 12 deletions sources/ftypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -1102,16 +1102,36 @@ typedef int (*TFUN1)();
#define DENSETABLE 1
#define SPARSETABLE 0

#define ONEPARTICLEIRREDUCIBLE 1
#define WITHINSERTIONS 2
#define NOTADPOLES 4
#define WITHSYMMETRIZE 8
#define TOPOLOGIESONLY 16
#define NONODES 32
#define WITHEDGES 64
#define CHECKEXTERN 128
#define WITHBLOCKS 256
#define WITHONEPI 512
#define NOSNAILS 1024
#define NOEXTSELF 2048
// Diagram generator flags. They should be powers of two, since they are added
// to pass to diagrams and masked in diawrap.cc to check the flags.
// We use a "stringified" version of these when defining the FORM preprocessor
// variables, so can't neatly use "1<<10" etc here.
#define TOPOLOGIESONLY 1
#define WITHOUTNODES 2
#define WITHEDGES 4
#define WITHBLOCKS 8
#define WITHONEPISETS 16
#define WITHSYMMETRIZEI 32
#define WITHSYMMETRIZEF 64
// This is not an "option" preprocessor var but is set by "external" particle definitions
#define CHECKEXTERN 128
// The "qgraf compatible" filtering flags:
#define ONEPARTI 256
#define ONEPARTR 512
#define ONSHELL 1024
#define OFFSHELL 2048
#define NOSIGMA 4096
#define SIGMA 8192
#define NOSNAIL 16384
#define SNAIL 32768
#define NOTADPOLE 65536
#define TADPOLE 131072
#define SIMPLE 262144
#define NOTSIMPLE 524288
#define BIPART 1048576
#define NONBIPART 2097152
#define CYCLI 4194304
#define CYCLR 8388608
#define FLOOP 16777216
#define NOTFLOOP 33554432

10 changes: 8 additions & 2 deletions sources/grcc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7242,16 +7242,22 @@ Bool EGraph::optQGrafA(Options *opt)
printf("optQGrafA: %8ld\n", mId);
econn->print();
#endif
Bool retval = True;
if (opt->qgopt[GRCC_QGRAF_OPT_FLOOP] != 0) {
for (int fl=0; fl < nFlines; fl++) {
if (flines[fl]->ftype == FL_Closed) {
if (flines[fl]->nlist % 2 != 0) {
return False;
retval = False;
break;
}
}
}
// `notfloop_' is the dual of `floop_', so flip the decision:
if (opt->qgopt[GRCC_QGRAF_OPT_FLOOP] == -1) {
retval = (retval == True ? False : True);
}
}
return True;
return retval;
}

//--------------------------------------------------------------
Expand Down
3 changes: 2 additions & 1 deletion sources/grccparam.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ typedef struct {
#define GRCC_QGRAF_OPT_BIPART 6
#define GRCC_QGRAF_OPT_CYCLI 7
#define GRCC_QGRAF_OPT_FLOOP 8
#define GRCC_QGRAF_OPT_TOPOL 9
//TODO what does this do? Does it work?
//#define GRCC_QGRAF_OPT_TOPOL 9

#ifdef GRCC_QGRAF_OPT_TOPOL
#define GRCC_QGRAF_OPT_Size 10
Expand Down
43 changes: 30 additions & 13 deletions sources/startup.c
Original file line number Diff line number Diff line change
Expand Up @@ -1205,20 +1205,37 @@ void StartVariables(void)
PutPreVar((UBYTE *)"keepright_",(UBYTE *)("0"),0,0);
PutPreVar((UBYTE *)"SYSTEMERROR_",(UBYTE *)("0"),0,0);
/*
Next are a few 'constants' for diagram generation
Next are the flags to control diagram generation filters
*/
PutPreVar((UBYTE *)"ONEPI_",(UBYTE *)("1"),0,0);
PutPreVar((UBYTE *)"WITHOUTINSERTIONS_",(UBYTE *)("2"),0,0);
PutPreVar((UBYTE *)"NOTADPOLES_",(UBYTE *)("4"),0,0);
PutPreVar((UBYTE *)"SYMMETRIZE_",(UBYTE *)("8"),0,0);
PutPreVar((UBYTE *)"TOPOLOGIESONLY_",(UBYTE *)("16"),0,0);
PutPreVar((UBYTE *)"NONODES_",(UBYTE *)("32"),0,0);
PutPreVar((UBYTE *)"WITHEDGES_",(UBYTE *)("64"),0,0);
/* Note that CHECKEXTERN is 128 */
PutPreVar((UBYTE *)"WITHBLOCKS_",(UBYTE *)("256"),0,0);
PutPreVar((UBYTE *)"WITHONEPISETS_",(UBYTE *)("512"),0,0);
PutPreVar((UBYTE *)"NOSNAILS_",(UBYTE *)("1024"),0,0);
PutPreVar((UBYTE *)"NOEXTSELF_",(UBYTE *)("2048"),0,0);
#define STR2(x) #x
#define STR(x) STR2(x)
PutPreVar((UBYTE *)"TOPOLOGIESONLY_" ,(UBYTE*)(STR(TOPOLOGIESONLY)) ,0,0);
PutPreVar((UBYTE *)"WITHOUTNODES_" ,(UBYTE*)(STR(WITHOUTNODES)) ,0,0);
PutPreVar((UBYTE *)"WITHEDGES_" ,(UBYTE*)(STR(WITHEDGES)) ,0,0);
PutPreVar((UBYTE *)"WITHBLOCKS_" ,(UBYTE*)(STR(WITHBLOCKS)) ,0,0);
PutPreVar((UBYTE *)"WITHONEPISETS_" ,(UBYTE*)(STR(WITHONEPISETS)) ,0,0);
PutPreVar((UBYTE *)"WITHSYMMETRIZEI_",(UBYTE*)(STR(WITHSYMMETRIZEI)),0,0);
PutPreVar((UBYTE *)"WITHSYMMETRIZEF_",(UBYTE*)(STR(WITHSYMMETRIZEF)),0,0);
// This is not an "option" preprocessor var but is set by "external" particle definitions
// PutPreVar((UBYTE *)"CHECKEXTERN_" ,(UBYTE*)(STR(CHECKEXTERN)) ,0,0);
PutPreVar((UBYTE *)"ONEPI_" ,(UBYTE*)(STR(ONEPARTI)) ,0,0);
PutPreVar((UBYTE *)"ONEPR_" ,(UBYTE*)(STR(ONEPARTR)) ,0,0);
PutPreVar((UBYTE *)"ONSHELL_" ,(UBYTE*)(STR(ONSHELL)) ,0,0);
PutPreVar((UBYTE *)"OFFSHELL_" ,(UBYTE*)(STR(OFFSHELL)) ,0,0);
PutPreVar((UBYTE *)"NOSIGMA_" ,(UBYTE*)(STR(NOSIGMA)) ,0,0);
PutPreVar((UBYTE *)"SIGMA_" ,(UBYTE*)(STR(SIGMA)) ,0,0);
PutPreVar((UBYTE *)"NOSNAIL_" ,(UBYTE*)(STR(NOSNAIL)) ,0,0);
PutPreVar((UBYTE *)"SNAIL_" ,(UBYTE*)(STR(SNAIL)) ,0,0);
PutPreVar((UBYTE *)"NOTADPOLE_" ,(UBYTE*)(STR(NOTADPOLE)) ,0,0);
PutPreVar((UBYTE *)"TADPOLE_" ,(UBYTE*)(STR(TADPOLE)) ,0,0);
PutPreVar((UBYTE *)"SIMPLE_" ,(UBYTE*)(STR(SIMPLE)) ,0,0);
PutPreVar((UBYTE *)"NOTSIMPLE_" ,(UBYTE*)(STR(NOTSIMPLE)) ,0,0);
PutPreVar((UBYTE *)"BIPART_" ,(UBYTE*)(STR(BIPART)) ,0,0);
PutPreVar((UBYTE *)"NONBIPART_" ,(UBYTE*)(STR(NONBIPART)) ,0,0);
PutPreVar((UBYTE *)"CYCLI_" ,(UBYTE*)(STR(CYCLI)) ,0,0);
PutPreVar((UBYTE *)"CYCLR_" ,(UBYTE*)(STR(CYCLR)) ,0,0);
PutPreVar((UBYTE *)"FLOOP_" ,(UBYTE*)(STR(FLOOP)) ,0,0);
PutPreVar((UBYTE *)"NOTFLOOP_" ,(UBYTE*)(STR(NOTFLOOP)) ,0,0);

{
char buf[41]; /* up to 128-bit */
Expand Down