FORM v5.0.0-35-g6318119
model.c
Go to the documentation of this file.
1
5/* #[ License : */
6/*
7 * Copyright (C) 1984-2026 J.A.M. Vermaseren
8 * When using this file you are requested to refer to the publication
9 * J.A.M.Vermaseren "New features of FORM" math-ph/0010025
10 * This is considered a matter of courtesy as the development was paid
11 * for by FOM the Dutch physics granting agency and we would like to
12 * be able to track its scientific use to convince FOM of its value
13 * for the community.
14 *
15 * This file is part of FORM.
16 *
17 * FORM is free software: you can redistribute it and/or modify it under the
18 * terms of the GNU General Public License as published by the Free Software
19 * Foundation, either version 3 of the License, or (at your option) any later
20 * version.
21 *
22 * FORM is distributed in the hope that it will be useful, but WITHOUT ANY
23 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
24 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
25 * details.
26 *
27 * You should have received a copy of the GNU General Public License along
28 * with FORM. If not, see <http://www.gnu.org/licenses/>.
29 */
30/* #] License : */
31/*
32 #[ Explanations :
33
34 This is a second generation much simplified version of model.c
35 Syntax:
36 Model QED;
37 Particle electron,positron,-2;
38 Particle photon,+3;
39 Vertex electron,positron,photon: g;
40 EndModel;
41 or:
42 Model QCD;
43 Particle quark,antiquark,-2;
44 Particle ghost,antighost,-1;
45 Particle gluon,+3;
46 Vertex quark,antiquark,gluon: g;
47 Vertex qhost,antighost,gluon: g;
48 Vertex gluon,gluon,gluon: g;
49 Vertex gluon,gluon,gluon,gluon: g^2;
50 EndModel;
51 Remarks:
52 1: if no second particle is given, a particle and its antiparticle are the same
53 2: Spin statistics is by dimension of SU(2) representation with a sign.
54 3: In a vertex we need to mention the coupling constants.
55 4: Internally a particle gives a vertex with only two lines.
56 5: All particles must have been declared before any vertex.
57
58 The diagrams should be provided as a collection of nodes and edges
59 with momenta with a direction substituted. The other parameters (like
60 Lorentz indices, color indices etc.) can then be provided in a procedure
61 that should go with this mode definition.
62 In principle the edges are not needed if there are no 'insertions', but
63 because we would like to have the insertions as well we need the edges.
64
65 #] Explanations :
66 #[ Includes : model.c
67*/
68
69#include "form3.h"
70
71/*
72 #] Includes :
73 #[ CreateVertex :
74*/
75
76VERTEX *CreateVertex(MODEL *m)
77{
78 VERTEX *v, **new;
79 WORD newsize;
80 int i;
81 if ( m->invertices >= m->sizevertices ) {
82 if ( m->sizevertices == 0 ) newsize = 20;
83 else newsize = 2*m->sizevertices;
84 new = (VERTEX **)Malloc1(newsize*sizeof(VERTEX *),"m->vertices");
85 for ( i = 0; i < m->sizevertices; i++ ) new[i] = m->vertices[i];
86 if ( m->sizevertices > 0 ) M_free(m->vertices,"m->vertices");
87 m->vertices = new;
88 m->sizevertices = newsize;
89 }
90 v = (VERTEX *)Malloc1(sizeof(VERTEX),"VERTEX");
91 m->vertices[m->invertices++] = v;
92 v->nparticles = 0;
93 v->ncouplings = 0;
94 v->type = 0;
95 v->error = 0;
96 v->externonly = 0;
97 v->spare = 0;
98 return(v);
99}
100
101/*
102 #] CreateVertex :
103 #[ ReadParticle :
104*/
105
106UBYTE *ReadParticle(UBYTE *s, VERTEX *v, MODEL *m, int par)
107{
108 UBYTE *name, c;
109 PARTICLE *p = v->particles + v->nparticles++;
110 WORD type, funnum;
111 int i, j;
112 SKIPBLANKS(s)
113 name = s; s = SkipName(s); c = *s; *s = 0;
114 if ( GetVar(name,&type,&funnum,CFUNCTION,NOAUTO) == NAMENOTFOUND ) {
115 p->number = AddFunction(name,0,VERTEXFUNCTION,0,0,0,-1,-1) + FUNCTION;
116 }
117 else if ( par == 1 && type == CFUNCTION && functions[funnum].spec == VERTEXFUNCTION ) {
118 p->number = funnum+FUNCTION;
119 }
120 else if ( par == 0 && type == CFUNCTION && functions[funnum].spec == VERTEXFUNCTION ) {
121/*
122 We should check whether this particle exists already in this model.
123 If so, this will be an error.
124*/
125 for ( i = 0; i < m->nparticles-1; i++ ) {
126 for ( j = 0; j < m->vertices[i]->nparticles; j++ ) {
127 if ( m->vertices[i]->particles[j].number == funnum ) {
128 MesPrint("&Illegal attempt to redefine a particle in the same model: %s",name);
129 v->error = 1;
130 }
131 }
132 }
133 p->number = funnum+FUNCTION;
134 }
135 else {
136 MesPrint("&Name of particle previously declared as another variable: %s",name);
137 v->error = 1;
138 }
139 *s = c;
140 while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
141 return(s);
142}
143
144/*
145 #] ReadParticle :
146 #[ CoModel :
147*/
148
149int CoModel(UBYTE *s)
150{
151 UBYTE *name, c;
152 MODEL *m = (MODEL *)Malloc1(sizeof(MODEL),"Model");
153 WORD numberofset, *e;
154 SETS set;
155 SKIPBLANKS(s)
156 AC.ModelLevel++;
157 int i;
158/*
159 We now have to add the model to the list of models.
160*/
161 if ( AC.modelspace == 0 || AC.nummodels >= AC.modelspace ) {
162 int newspace = 2*AC.modelspace+2, i;
163 MODEL **models = (MODEL **)Malloc1((sizeof(MODEL *))*newspace,"AC.models");
164 for ( i = 0; i < AC.modelspace; i++ ) models[i] = AC.models[i];
165 if ( AC.models ) M_free(AC.models,"AC.models");
166 AC.modelspace = newspace;
167 AC.models = models;
168 }
169
170 AC.models[AC.nummodels++] = m;
171
172 m->vertices = 0;
173 m->couplings = 0;
174 m->nparticles = m->nvertices = m->sizevertices = m->invertices = 0;
175 m->sizecouplings = 0;
176 m->error = 0;
177 m->grccmodel = NULL;
178
179 name = s;
180 if ( FG.cTable[*s] == 0 ) {
181 while ( FG.cTable[*s] <= 1 ) s++;
182 c = *s; *s = 0;
183 m->name = strDup1(name,"Model name");
184 *s = c;
185 SKIPBLANKS(s)
186 if ( *s != 0 ) {
187 MesPrint("&Illegal option in model statement: %s",s);
188 return(1);
189 }
190 }
191 else {
192 m->name = strDup1((UBYTE *)"---","Model name");
193 m->error = 1;
194 MesPrint("&Illegal name for model: %s",name);
195 return(1);
196 }
197/*
198 Now make it a set with one element. The type of the set is rather special
199*/
200 if ( GetName(AC.varnames,m->name,&numberofset,NOAUTO) != NAMENOTFOUND ) {
201 MesPrint("&Name conflict with name %s of model",m->name);
202 return(1);
203 }
204 numberofset = AddSet(name,0);
205 set = Sets + numberofset;
206 set->type = CMODEL;
207 e = (WORD *)FromVarList(&AC.SetElementList);
208 *e = AC.nummodels-1;
209 set->last++;
210 AC.SetList.numtemp = AC.SetList.num;
211 AC.SetElementList.numtemp = AC.SetElementList.num;
212
213 for ( i = 0; i <= MAXLEGS; i++ ) m->legcouple[i] = 0;
214 m->legcouple[2] = 1;
215
216 return(0);
217}
218
219/*
220 #] CoModel :
221 #[ CoParticle :
222*/
223
224int CoParticle(UBYTE *s)
225{
226 MODEL *m;
227 VERTEX *v;
228 int i;
229 if ( AC.nummodels <= 0 ) {
230 MesPrint("&No open model for particle statement");
231 return(1);
232 }
233 m = AC.models[AC.nummodels-1];
234 if ( m->nvertices > 0 ) {
235 MesPrint("&In a model description Particle statements should be before Vertex statements.");
236 m->error = 1;
237 return(1);
238 }
239 v = CreateVertex(m);
240 m->nparticles++;
241 s = ReadParticle(s,v,m,0);
242 v->particles[0].type = 1;
243 while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
244 if ( v->error == 0 ) {
245 if ( FG.cTable[*s] == 0 ) {
246 s = ReadParticle(s,v,m,0);
247 v->particles[1].type = -1;
248 if ( v->particles[0].number == v->particles[1].number ) {
249 v->particles[0].type = 0;
250 v->particles[1].type = 0;
251 }
252 }
253 else { /* Particle = antiparticle */
254 v->particles[1] = v->particles[0];
255 v->nparticles++;
256 v->particles[0].type = 0;
257 v->particles[1].type = 0;
258 }
259 }
260 if ( v->error == 0 && ( *s == '+' || *s == '-' ) ) {
261 int x = 0, sign = ( *s == '-' ) ? -1: 1;
262 s++;
263 while ( FG.cTable[*s] == 1 ) { x = 10*x + *s++ - '0'; }
264 if ( x == 0 ) {
265 v->error = 1;
266 MesPrint("&Spin goes by dimension of SU(2) representation. Zero is not allowed.");
267 }
268 else { v->particles[0].spin = v->particles[1].spin = sign*x; }
269 SKIPBLANKS(s)
270 }
271 else if ( v->error == 0 ) {
272 v->particles[0].spin = v->particles[1].spin = 1;
273 v->particles[0].type = 0;
274 v->particles[1].type = 0;
275 }
276/*
277 Here will come future options
278*/
279 while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
280 while ( v->error == 0 && *s != 0 && FG.cTable[*s] == 0 ) {
281 UBYTE *opt = s, c;
282 while ( FG.cTable[*s] == 0 ) s++;
283 c = *s; *s = 0;
284 if ( StrICont(opt,(UBYTE *)"external") == 0 ) { v->externonly = 1; }
285 else {
286 MesPrint("&Unrecognized option %s in particle statement.",opt);
287 v->error = 1;
288 }
289 *s = c;
290 while ( *s == ',' || *s == ' ' || *s == '\t' ) s++;
291 }
292/*
293 The couplings array will be used for registering in what kind of vertices the
294 particle is involved. (example: in QCD the quarks only in 2 and 3-point vertices)
295*/
296 for ( i = 0; i < MAXPARTICLES; i++ ) v->couplings[i] = 0;
297 v->couplings[2] = 1;
298 return(v->error);
299}
300
301/*
302 #] CoParticle :
303 #[ CoVertex :
304*/
305
306int CoVertex(UBYTE *s)
307{
308 UBYTE *ss, *name, c;
309 WORD type;
310 MODEL *m;
311 VERTEX *v;
312 if ( AC.ModelLevel <= 0 ) {
313 MesPrint("&No open model for vertex statement");
314 return(1);
315 }
316 m = AC.models[AC.nummodels-1];
317/*
318 Get an object of type VERTEX
319*/
320 v = CreateVertex(m);
321 m->nvertices++;
322 SKIPBLANKS(s);
323 while ( *s && *s != ':' ) {
324 if ( v->error == 0 ) {
325 s = ReadParticle(s,v,m,1);
326 if ( v->error ) m->error = 1;
327 }
328 else {
329 while ( *s && *s != ':' ) {
330 if ( *s == '[' ) { SKIPBRA1(s) }
331 else if ( *s == '(' ) { SKIPBRA3(s) }
332 else if ( *s == 0 ) {
333 v->error = 1;
334 MesPrint("&No coupling constant in vertex statement.");
335 break;
336 }
337 }
338 break;
339 }
340 }
341 if ( v->error == 0 ) {
342 if ( *s == ':' ) { /* read symbols and powers */
343 s++; SKIPBLANKS(s);
344 while ( *s ) {
345 if ( v->ncouplings >= 2*MAXCOUPLINGS ) {
346 MesPrint("&More than %d coupling constants in vertex.",(WORD)MAXCOUPLINGS);
347 MesPrint(" Recompile with a larger value for MAXCOUPLINGS.");
348 return(1);
349 }
350 ss = s; s = SkipName(s); c = *s; *s = 0; name = ConstructName(ss,0);
351 // Forbid couplings which have no symbol or an overal numerical factor.
352 if ( *name == 0 ) {
353 v->error = 1;
354 MesPrint("&Invalid coupling constant in vertex statement.");
355 }
356 if ( GetVar(name,&type,&v->couplings[v->ncouplings],CSYMBOL,WITHAUTO)
357 == NAMENOTFOUND ) {
358 WORD minpow = -MAXPOWER;
359 WORD maxpow = MAXPOWER;
360 WORD cplx = 0, dim = 0;
361 v->couplings[v->ncouplings] = AddSymbol(name,minpow,maxpow,cplx,dim);
362 }
363 *s = c;
364 v->ncouplings++;
365/*
366 Now possibly a power
367*/
368 if ( *s == '^' ) { /* we need an integer */
369 WORD x = 0; WORD sign = 1;
370 s++;
371 while ( *s == '-' || *s == '+' ) {
372 if ( *s == '-' ) sign = -sign;
373 s++;
374 }
375 if ( sign == -1 ) {
376 v->error = 1;
377 MesPrint("&Invalid negative power of coupling constant.");
378 }
379 while ( FG.cTable[*s] == 1 ) x = 10*x + *s++ - '0';
380 v->couplings[v->ncouplings++] = x;
381 }
382 else {
383 v->couplings[v->ncouplings++] = 1;
384 }
385 SKIPBLANKS(s);
386 if ( *s == '*' ) { s++; continue; }
387 if ( *s != ',' ) break;
388 s++;
389 SKIPBLANKS(s);
390 }
391 }
392 else {
393 v->error = 1;
394 MesPrint("&A vertex statement needs at least one coupling constant.");
395 }
396 }
397 if ( v->error == 0 ) {
398/*
399 Register which types of vertices are possible for each particle.
400*/
401 int i, j;
402 for ( i = 0; i < v->nparticles; i++ ) {
403 for ( j = 0; j < m->nparticles; j++ ) {
404 if ( m->vertices[j]->particles[0].number == v->particles[i].number ) break;
405 if ( m->vertices[j]->particles[1].number == v->particles[i].number ) break;
406 }
407 m->vertices[j]->couplings[v->nparticles] = 1;
408 }
409 }
410 return(v->error);
411}
412
413/*
414 #] CoVertex :
415 #[ CoEndModel :
416*/
417
418int CoEndModel(UBYTE *s)
419{
420 int i, j, k, kk;
421 WORD csize = 0, *newcouplings, newsize;
422 MODEL *m;
423 VERTEX *v;
424 if ( AC.ModelLevel <= 0 ) {
425 MesPrint("&EndModel statement without matching Model statement");
426 return(1);
427 }
428 m = AC.models[AC.nummodels-1];
429/*
430 Now create a list of all coupling constants.
431 Note that we do not expect an astronomical number of them and hence
432 we use a simple insertion algorithm.
433*/
434 m->ncouplings = 0;
435 for ( i = 0; i < m->nvertices; i++ ) {
436 v = m->vertices[i+m->nparticles];
437 m->legcouple[v->nparticles] = 1;
438 if ( m->ncouplings + v->ncouplings > csize ) {
439 if ( csize == 0 ) newsize = v->ncouplings + 10;
440 else newsize = 2*csize;
441 newcouplings = (WORD *)Malloc1(newsize*sizeof(WORD),"m->couplings");
442 for ( k = 0; k < m->ncouplings; k++ ) newcouplings[k] = m->couplings[k];
443 if ( csize > 0 ) M_free(m->couplings,"m->couplings");
444 m->couplings = newcouplings;
445 csize = newsize;
446 }
447 for ( j = 0; j < v->ncouplings; j += 2 ) {
448 WORD sym = v->couplings[j];
449 for ( k = 0; k < m->ncouplings; k++ ) {
450 if ( sym == m->couplings[k] ) break;
451 if ( sym < m->couplings[k] ) {
452 for ( kk = m->ncouplings; kk > k; k-- )
453 m->couplings[kk] = m->couplings[kk-1];
454 m->couplings[k] = sym;
455 m->ncouplings++;
456 break;
457 }
458 }
459 if ( k >= m->ncouplings ) m->couplings[m->ncouplings++] = sym;
460 }
461 }
462 AC.ModelLevel--;
463 DUMMYUSE(s)
464 return(LoadModel(m));
465}
466
467/*
468 #] CoEndModel :
469*/