source: TRACY3/branches/tracy3-3.10.1b/tracy/tracy/src/soleillib.cc @ 23

Last change on this file since 23 was 23, checked in by zhangj, 10 years ago

Clean version of Tracy: SoleilVersion at the end of 2011.Use this clean version to find the correct dipole fringe field to have the correct FMAP and FMAPDP of ThomX. Modified files: tpsa_lin.cc, soleillib.cc, prtmfile.cc, rdmfile.cc, read_script.cc, physlib.cc, tracy.cc, t2lat.cc, t2elem.cc, naffutils.cc in /tracy/tracy/src folder; naffutils.h, tracy_global.h, physlib.h, tracy.h, read_script.h, solielilib.h, t2elem.h in /tracy/tracy.inc folder; soltracy.cc in tracy/tools folder

  • Property svn:executable set to *
File size: 203.3 KB
Line 
1/* Tracy-3
2
3   J. Bengtsson, CBP, LBL      1990 - 1994   Pascal version
4                 SLS, PSI      1995 - 1997
5   M. Boege      SLS, PSI      1998          C translation
6   L. Nadolski   SOLEIL        2002          Link to NAFF, Radia field maps
7   J. Bengtsson  NSLS-II, BNL  2004 -       
8   J. Zhang      SOLEIL        2010         ADD SOLEIL PARTS IN TRACY 2.7
9*/
10
11
12/****************************************************************************/
13/* void Get_Disp_dp(void)
14
15   Purpose:
16       Get dispersion w/ energy offset
17
18   Input:
19       none
20
21   Output:
22       none
23
24   Return:
25       none
26
27   Global variables:
28       trace
29
30   specific functions:
31       getcod, Ring_GetTwiss, getelem
32
33   Comments:
34       none
35
36****************************************************************************/
37void Get_Disp_dp(void)
38{
39  long i;
40//  long lastpos = 0;
41  const char nomfic[] = "dispersion.out";
42  FILE *outf;
43  double dP = 0e0;
44  CellType Cell;
45  long lastpos =0L;
46
47  if (trace) fprintf(stdout,"Entering Get_Disp_dp function ...\n");
48
49  if ((outf = fopen(nomfic, "w")) == NULL)
50  {
51    fprintf(stdout, "Get_Disp_dp: Error while opening file %s\n",nomfic);
52    exit_(1);
53  }
54
55  for (i = 1; i <= 20; i++) {
56    dP = -0.003 + 1e-6 + i*0.0006;
57    getcod(dP, lastpos);
58    Ring_GetTwiss(true, dP);  /* Compute and get Twiss parameters */
59    getelem(0, &Cell);
60    fprintf(outf,"%+e %+e %+e\n", dP, Cell.BeamPos[0], Cell.Eta[0]);
61  }
62
63  fclose(outf);
64}
65
66/****************************************************************************/
67/* void InducedAmplitude(long spos)
68
69   Purpose:
70      Compute the induced amplitude for a particle getting for a energy offset dP
71        process similar to a Touschek scattering
72        The induced amplitude is transported to the first element of the lattice
73        by scaling the maplitude with energy dependent betafunctions       
74
75   Input:
76       spos : position where Touschek scattering occurs
77
78   Output:
79       amp_ind.out
80
81   Return:
82       none
83
84   Global variables:
85       none
86
87   specific functions:
88       none
89
90   Comments:
91       none
92
93****************************************************************************/
94void InducedAmplitude(long spos)
95{
96  Vector        x1;     /* tracking coordinates */
97  long          i = 0L, k = 0L, imax = 50;
98  FILE *        outf;
99  double        dP = 0.0, dP20 = 0.0, dpmax = 0.06;
100  Vector2       amp = {0.0, 0.0}, H = {0.0, 0.0};
101  const char    nomfic[] = "amp_ind.out";
102  long          lastpos = 0;
103  CellType      Celldebut, Cell;
104  Vector        codvector[Cell_nLocMax];
105
106  globval.Cavity_on  = false;    /* Cavity on/off */
107  globval.radiation  = false;    /* radiation on/off */
108
109  /* Ouverture fichier moustache */
110  if ((outf = fopen(nomfic, "w")) == NULL)
111  {
112    fprintf(stdout, "Error when open filename %s\n",nomfic);
113    exit_(1);
114  }
115
116  fprintf(outf, "# Induced amplitude transported at lattice entrance\n");
117  fprintf(outf, "#    dp           xind         zind       "
118                     " Betax(entrance) Betaz(entrance)       Betax         betaz"
119                     "       Hx(delta)/delta^2    Hz(delta)/delta^2    "
120                     " Hx(delta)  Hz(delta)      etax(delta)        etaxp(delta)\n#\n");
121
122
123  lastpos = 1;
124 
125  for (k = 0; k <= imax ; k++)  {
126    dP = -dpmax + 2*dpmax*k/imax;
127    /* Coordonnees initiales */
128    x1[0] = 0.0; x1[1] = 0.0;
129    x1[2] = 0.0; x1[3] = 0.0;
130    x1[4] = dP ; x1[5] = 0.0;
131
132    /* Computes closed orbit and store it in a vector */
133    set_vectorcod(codvector, dP) ;
134    Ring_GetTwiss(false, dP);  /* Compute and get Twiss parameters */
135    getelem(1L, &Celldebut);
136    getelem(spos, &Cell);
137
138    /* compute H at s =spos */
139    dP20 = ((dP == 0) ? 1.0 : dP*dP);
140    i = 0; /* Horizontal */
141    H[i] = ((1.0+Cell.Alpha[i]*Cell.Alpha[i])/Cell.Beta[i]*codvector[spos][0]*codvector[spos][0]+
142            2.0*Cell.Alpha[i]*codvector[spos][0]*codvector[spos][1]+
143            Cell.Beta[i]*codvector[spos][1]*codvector[spos][1])/dP20;
144    i = 1; /* Vertical */
145    H[i] = ((1.0+Cell.Alpha[i]*Cell.Alpha[i])/Cell.Beta[i]*codvector[spos][2]*codvector[spos][2]+
146            2.0*Cell.Alpha[i]*codvector[spos][2]*codvector[spos][3]+
147            Cell.Beta[i]*codvector[spos][3]*codvector[spos][3])/dP20;
148
149    amp[0] = codvector[spos][0]*sqrt(Celldebut.Beta[0]/Cell.Beta[0]);
150    amp[1] = codvector[spos][1];
151
152    fprintf(outf, "%+10.5e %+10.5e %+10.5e %+10.5e %+10.5e %+10.5e %+10.5e "
153                  "%+10.5e %+10.5e %+10.5e %+10.5e %+10.5e %+10.5e \n",                                 
154                  dP, codvector[spos][0], codvector[spos][1], 
155                  Celldebut.Beta[0], Celldebut.Beta[1], Cell.Beta[0], Cell.Beta[1], 
156                  H[0], H[1], H[0]*dP20, H[1]*dP20, Cell.Eta[0], Cell.Etap[0]); 
157    }
158  fclose(outf);
159}
160
161/****************************************************************************/
162/* void Hfonction(long pos, double dP)
163
164   Purpose:
165     Compute the Hfunction at position pos for the energy offset dP
166     H is wrong at large dp since eta and eta' are computed
167       by numerical differentiation, which means that
168       eta(dp) = eta0 + eta2*dp*dp + O(4) instead of
169       eta(dp) = eta0 + eta1*dp + eta2*dp*dp + O(3)
170
171     A solution is to compute eta from the closed orbit by:
172       xco(dp) = eta(dp)*dp => eta(dp) = xco(dp)/dp
173       WARNING: this definition is true only if the lattice
174       is perfect.
175       Indeed in general : xco = eta(dp)*dp + x0(defaults)
176
177   Input:
178       pos:    element index in the lattice.
179
180   Output:
181       none
182
183   Return:
184       none
185
186   Global variables:
187       none
188
189   specific functions:
190       Ring_GetTwiss
191       getelem
192
193   Comments:
194       none
195
196****************************************************************************/
197
198//void Hfonction(long pos, double dP,Vector2 H)
199void Hfonction(long pos, double dP)
200{
201  CellType Cell;
202  long i;
203Vector2 H;
204
205  Ring_GetTwiss(true, dP); /* Compute and get Twiss parameters */
206  getelem(pos, &Cell);    /* Position of the element pos */
207
208  i = 0; /* Horizontal */
209  H[i] = (1+Cell.Alpha[i]*Cell.Alpha[i])/Cell.Beta[i]*Cell.Eta[i]*Cell.Eta[i]+
210          2*Cell.Alpha[i]*Cell.Eta[i]*Cell.Etap[i]+
211          Cell.Beta[i]*Cell.Etap[i]*Cell.Etap[i];
212  i = 1; /* Vertical */
213  H[i] = (1+Cell.Alpha[i]*Cell.Alpha[i])/Cell.Beta[i]*Cell.Eta[i]*Cell.Eta[i]+
214          2*Cell.Alpha[i]*Cell.BeamPos[i]*Cell.Etap[i]+
215    Cell.Beta[i]*Cell.Etap[i]*Cell.Etap[i];
216}
217
218/****************************************************************************/
219/* void Hcofonction(long pos, double dP)
220
221   Purpose:
222       Compute the true Hfunction defined by the chromatic closed orbit
223       at position pos and for a energy offset dP
224
225       For a givien delta
226       H = gamma xcod² + 2*alpha*xcod*xcod' + beta*xcod'*xcod'
227       
228   Input:
229       none
230
231   Output:
232       none
233
234   Return:
235       none
236
237   Global variables:
238       none
239
240   specific functions:
241       getcod
242       Ring_GetTwiss
243       getelem
244
245   Comments:
246       Bug: Cell.BeamPos does not give closed orbit !!!
247
248****************************************************************************/
249//void Hcofonction(long pos, double dP,Vector2 H)
250void Hcofonction(long pos, double dP)
251{
252  CellType Cell;
253  long i;
254  long lastpos = 1L;
255  Vector2 H;
256  getcod(dP, lastpos);   /* determine closed orbit */
257
258  if (lastpos != globval.Cell_nLoc) printf("Ring unstable for dp=%+e @ pos=%ld\n", dP, lastpos);
259
260  Ring_GetTwiss(true, dP); /* Compute and get Twiss parameters */
261  getelem(pos, &Cell);    /* Position of the element pos */
262
263  i = 0; /* Horizontal */
264  H[i] = (1+Cell.Alpha[i]*Cell.Alpha[i])/Cell.Beta[i]*Cell.BeamPos[i]*Cell.BeamPos[i]+
265          2*Cell.Alpha[i]*Cell.BeamPos[i]*Cell.BeamPos[i+1]+
266          Cell.Beta[i]*Cell.BeamPos[i+1]*Cell.BeamPos[i+1];
267  i = 1; /* Vertical */
268  H[i] = (1+Cell.Alpha[i]*Cell.Alpha[i])/Cell.Beta[i]*Cell.BeamPos[i+1]*Cell.BeamPos[i+1]+
269          2*Cell.Alpha[i]*Cell.BeamPos[i+1]*Cell.BeamPos[i+2]+
270          Cell.Beta[i]*Cell.BeamPos[i+2]*Cell.BeamPos[i+2];
271  fprintf(stdout,"H[0]=%10.6f,H[1]=%10.6f\n",H[0],H[1]);
272}
273
274 
275/****************************************************************************/
276/* void SetErr(long seed,double fac)
277
278   Purpose:
279       Set error
280       Definir une distribution aleatoire de quadripoles tournes associee a chaque
281       quadripole de la machine
282       Distribution gaussienne d'ecart type fac et coupe a normcut*sigma
283       This function works for the lattice with full quadrupoles
284
285   Input:
286       seed: random seed number
287       fac :  RMS value of the rotation angle of the quadrupole
288   Output:
289       none
290
291   Return:
292       none
293
294   Global variables:
295       globval
296       HOMmax
297
298   specific functions:
299       setrandcut, initranf
300       getelem, putelem
301       Mpole_SetPB
302
303   Comments:
304       Only valid if quad split into two part (cf pair variable)
305       Rotation inversion to do as in BETA code
306       Test if normal quad sin(theta) = 0. Do not work if tilt error
307       
308       Modified by Jianfeng Zhang 19/01/2011 @soleil
309
310****************************************************************************/
311void SetErr(long seed,double fac)
312{
313  double  normcut = 0.0;
314  long    i = 0L;
315 // CellType Cell;
316  double theta = 0.0;
317  bool prt=false;
318 
319 
320  if(!prt){
321    printf("\n");
322    printf(" Setting random rotation errors to quadrupole magnets:\n");
323    printf("   random seed number is: %ld, rms value of the rotation error is: %lf rad\n",seed,fac);
324  }
325 
326  setrancut(normcut=2L);
327  iniranf(seed);
328
329  for (i = 1L; i <= globval.Cell_nLoc; i++)
330  {
331    if (Cell[i].Elem.Pkind == Mpole)
332    {
333      if (Cell[i].Elem.M->n_design == 2L && Cell[i].dT[1] == 0) //Quads but exclude skew quads
334      {
335        theta = fac*normranf(); /* random error every 2 elements (quad split into 2) */
336        Cell[i].Elem.M->PBpar[HOMmax-2L] = -Cell[i].Elem.M->PBpar[HOMmax+2L]*sin(2.0*theta);
337        Cell[i].Elem.M->PBpar[HOMmax+2L] =  Cell[i].Elem.M->PBpar[HOMmax+2L]*cos(2.0*theta);
338        if (trace) printf("%6s % .5e % .5e % .5e\n",Cell[i].Elem.PName,
339                           Cell[i].Elem.M->PBpar[HOMmax-2L], Cell[i].Elem.M->PBpar[HOMmax+2L],theta);
340
341        Mpole_SetPB(Cell[i].Fnum, Cell[i].Knum, -2L);
342        Mpole_SetPB(Cell[i].Fnum, Cell[i].Knum, 2L);
343      }
344    }
345  }
346}
347
348/****************************************************************************/
349/* void SetErr2(long seed,double fac)
350
351   Purpose:
352       Set error
353       Definir une distribution aleatoire de quadripoles tournes associee a chaque
354       quadripole de la machine
355       Distribution gaussienne d'ecart type fac et coupe a normcut*sigma
356       This function works for the lattice with two half quadrupoles
357
358   Input:
359       seed: random seed number
360       fac :  RMS value of the rotation angle of the quadrupole
361   Output:
362       none
363
364   Return:
365       none
366
367   Global variables:
368       globval
369       HOMmax
370
371   specific functions:
372       setrandcut, initranf
373       getelem, putelem
374       Mpole_SetPB
375
376   Comments:
377       Only valid if quad split into two part (cf pair variable)
378       Rotation inversion to do as in BETA code
379       Test if normal quad sin(theta) = 0. Do not work if tilt error
380       
381
382****************************************************************************/
383void SetErr2(long seed,double fac)
384{
385  double  normcut = 0.0;
386  long    i = 0L;
387 // CellType Cell;
388  double theta = 0.0;
389  int pair = 0;
390  bool prt=false;
391 
392 
393  if(!prt){
394    printf("\n");
395    printf(" Setting random rotation errors to quadrupole magnets:\n");
396    printf("   random seed number is: %ld, rms value of the rotation error is: %lf rad\n",seed,fac);
397  }
398 
399  setrancut(normcut=2L);
400  iniranf(seed);
401
402  for (i = 1L; i <= globval.Cell_nLoc; i++)
403  {
404    if (Cell[i].Elem.Pkind == Mpole)
405    {
406      if (Cell[i].Elem.M->n_design == 2L && Cell[i].dT[1] == 0) // exclude skew quads
407      {
408        if ((pair%2)==0) theta = fac*normranf(); /* random error every 2 elements (quad split into 2) */
409        pair++;
410        Cell[i].Elem.M->PBpar[HOMmax-2L] = -Cell[i].Elem.M->PBpar[HOMmax+2L]*sin(2.0*theta);
411        Cell[i].Elem.M->PBpar[HOMmax+2L] =  Cell[i].Elem.M->PBpar[HOMmax+2L]*cos(2.0*theta);
412        if (trace) printf("%6s % .5e % .5e % .5e\n",Cell[i].Elem.PName,
413                           Cell[i].Elem.M->PBpar[HOMmax-2L], Cell[i].Elem.M->PBpar[HOMmax+2L],theta);
414
415        Mpole_SetPB(Cell[i].Fnum, Cell[i].Knum, -2L);
416        Mpole_SetPB(Cell[i].Fnum, Cell[i].Knum, 2L);
417      }
418    }
419  }
420}
421
422/****************************************************************************/
423/* void ReadCh(Const char *AperFile)
424
425   Purpose:  read and set the definition of the vacuum chamber
426             between different sections around the ring from file
427             AperFile.dat.
428             
429             In AperFile.dat,
430               1) line begin with "#" is comment line
431               2) first line Name1: Start
432                  first line Name2: All
433               3) the numbers of MK1 and MK2 should be  the same in the lattice
434               4) MK1 is defined before MK2 in the lattice
435               5)
436                 MK1:  marker before the start element of the section for the aperture
437                 Mk2:  marker after the end element of the section for the aperture
438               dxmin:   minimum x value of vacuum chamber
439               dxmax:   maxmum x value of vacuum chamber
440               dymin:   minimum y value of vacuum chamber
441               dymax:   maxmum y value of vacuum chamber
442               
443
444
445   Input:
446       none
447
448   Output:
449       none
450
451   Return:
452       none
453
454   Global variables:
455       globval
456
457   specific functions:
458       none
459
460   Comments:
461       See also LoadApers in nsrl-ii.cc
462       J.Zhang 07/10 soleil
463****************************************************************************/
464void ReadCh(const char *AperFile)
465{
466 char    in[max_str], Name1[max_str], Name2[max_str];
467 char    *line;
468  int     Fnum1=0, Fnum2=0, Kidnum1=0, Kidnum2=0, k1=0, k2=0; 
469  int     i=0, j=0,LineNum=0;
470  double  dxmin=0.0, dxmax=0.0, dymin=0.0, dymax=0.0;  // min and max x and apertures
471  FILE    *fp;
472  bool  prt = false;
473
474  fp = file_read(AperFile);
475
476  printf("\n");
477  printf("Loading and setting vacuum apertures to lattice elements...\n");
478
479  while (line=fgets(in, max_str, fp)) {
480  /* kill preceding whitespace generated by "table" key
481        or "space" key, but leave \n
482        so we're guaranteed to have something*/
483     while(*line == ' ' || *line == '\t') {
484       line++;
485     }       
486    /* count the line number that has been read*/
487    LineNum++; 
488    /* NOT read comment line or blank line with the end of line symbol '\n','\r' or '\r\n'*/
489    if (strstr(line, "#") == NULL && strcmp(line,"\n") != 0 &&
490        strcmp(line,"\r") != 0 &&strcmp(line,"\r\n") != 0)
491    /* read the aperture setting */ 
492    {
493      sscanf(line,"%s %s %lf %lf %lf %lf",
494             Name1,Name2, &dxmin, &dxmax, &dymin, &dymax);
495     
496      if (strcmp("Start", Name1)==0 && strcmp("All", Name2)==0) {
497        if(prt)
498          printf("setting all apertures to \n"
499                 " dxmin = %e, dxmax = %e, dymin = %e, dymax = %e\n",
500                 dxmin, dxmax, dymin, dymax);
501        set_aper_type(All, dxmin, dxmax, dymin, dymax);
502        //      ini_aper(dxmin, dxmax, dymin, dymax);
503       }       
504       
505      else {
506        /* read the vacuum chamber between section */
507        Fnum1 = ElemIndex(Name1);
508        Fnum2 = ElemIndex(Name2);
509        if(Fnum1>0 && Fnum2>0) {
510          /* if element Name1 is defined before element Name2, give error message*/
511          if(Fnum1 > Fnum2){
512            printf("\nReadCh(): \n" 
513                   "          aperture file, Line %d, Element %s should be defined after Element %s \n",
514                    LineNum,Name1,Name2);
515            exit_(1);
516          }
517          /* if the element is not unique in the lattice, give error message*/
518          Kidnum1 = GetnKid(Fnum1);
519          Kidnum2 = GetnKid(Fnum2);
520          if(Kidnum1 != Kidnum2){
521           printf("\nReadCh(): \n"
522                  "          vacuum aperture file, Line %d, the number of Element %s is not equal to",
523                  " the number of  Element %s in lattice \n", LineNum,Name1,Name2);
524            exit_(1);
525          }
526           
527          if(prt)
528            printf("setting apertures to section:\n"
529                   "  %s  %s dxmin = %e, dxmax = %e, dymin = %e, dymax = %e\n",
530                   Name1, Name2, dxmin, dxmax, dymin, dymax);
531       
532       
533        /* set the vacuum chamber*/
534        //read the marker before the first element, and the markder after the last elment
535          for(i=0;i<Kidnum1;i++){
536            /* find the start and end index of the section*/
537            k1 = Elem_GetPos(Fnum1, i+1);
538            k2 = Elem_GetPos(Fnum2, i+1);
539           
540            for(j=1; j<globval.Cell_nLoc; j++){
541              if(j>=k1 && j<k2){
542                Cell[j].maxampl[X_][0] = dxmin;
543                Cell[j].maxampl[X_][1] = dxmax;
544                Cell[j].maxampl[Y_][0] = dymin;
545                Cell[j].maxampl[Y_][1] = dymax;
546              }
547           }
548         } 
549       }else {
550          printf("\nReadCh(): \n"
551                 "          aperture file, Line %d, lattice does not contain section between element %s and element %s\n", 
552                  LineNum,Name1, Name2); 
553          exit_(1);
554          }
555      }
556       
557    } 
558 //  else /* print the comment line */
559 //     printf("%s", line);
560  } 
561  fclose(fp);
562  // turn on the global flag for CheckAmpl()
563  globval.Aperture_on = true;
564 
565}
566
567/****************************************************************************/
568/* void Trac_Tab(double x, double px, double y, double py, double dp,
569 long nmax, long pos, long *lastn, long *lastpos, FILE *outf1, double Tx[][NTURN])
570
571   Purpose:
572       Single particle tracking over NTURN turns
573       The 6D phase trajectory is saved in a array
574
575   Input:
576       x, px, y, py 4 transverses coordinates
577       dp           energy offset
578       nmax         number of turns
579       pos          starting position for tracking
580       aperture     global physical aperture
581
582   Output:
583      lastn         last n (should be nmax if  not lost)
584      lastpos       last position in the ring
585      Tx            6xNTURN matrix of phase trajectory
586
587   Return:
588       none
589
590   Global variables:
591       NTURN number of turn for tracking
592       globval
593
594   specific functions:
595       Cell_Pass
596
597   Comments:
598       useful for connection with NAFF
599
600****************************************************************************/
601void Trac_Tab(double x, double px, double y, double py, double dp,
602              long nmax, long pos, long &lastn, long &lastpos, FILE *outf1,
603              double Tx[][NTURN])
604{
605  bool lostF = true; /* Lost particle Flag */
606  Vector x1;            /* tracking coordinates */
607  long i;
608  Vector2  aperture;
609  aperture[0] = 1e0; aperture[1] = 1e0;
610
611  x1[0] =  x; x1[1] = px;
612  x1[2] =  y; x1[3] = py;
613  x1[4] = dp; x1[5] = 0.0;
614
615  lastn = 0;
616  (lastpos)=pos;
617
618  Cell_Pass(pos, globval.Cell_nLoc, x1, lastpos);
619//Cell_Pass(pos -1, globval.Cell_nLoc, x1, lastpos);
620  if(trace) fprintf(outf1, "\n");
621
622  do {
623    (lastn)++;
624    if ((lastpos == globval.Cell_nLoc) &&
625        (fabs(x1[0]) < aperture[0]) && (fabs(x1[2]) < aperture[1]))
626     /* tracking entre debut anneau et element */
627    {
628     Cell_Pass(0,globval.Cell_nLoc, x1, lastpos);
629     if(trace) fprintf(outf1, "%6ld %+10.5e %+10.5e %+10.5e %+10.5e"
630                       " %+10.5e %+10.5e \n",
631                       lastn, x1[0], x1[1], x1[2], x1[3], x1[4], x1[5]);
632     i = (lastn)-1;
633     Tx[0][i] = x1[0]; Tx[1][i] = x1[1];
634     Tx[2][i] = x1[2]; Tx[3][i] = x1[3];
635     Tx[4][i] = x1[4]; Tx[5][i] = x1[5];
636
637    }
638    else  {
639      printf("Trac_Tab: Particle lost \n");
640      fprintf(stdout, "%6ld %+10.5g %+10.5g %+10.5g"
641                      " %+10.5g %+10.5g %+10.5g \n",
642                      lastn, x1[0], x1[1], x1[2], x1[3], x1[4], x1[5]);
643      lostF = false;
644    }
645   }
646   while (((lastn) < nmax) && ((lastpos) == globval.Cell_nLoc) && (lostF == true));
647
648
649   for (i = 1; i < nmax; i++) {
650     fprintf(outf1, "%6ld %+10.5e %+10.5e %+10.5e %+10.5e %+10.5e %+10.5e \n", i,
651                     Tx[0][i], Tx[1][i], Tx[2][i], Tx[3][i], Tx[4][i], Tx[5][i]);
652   }
653}
654
655
656
657/****************************************************************************/
658/* void TunesShiftWithAmplitude(long Nbx, long Nbz, long Nbtour, double xmax, double zmax,
659               double energy)
660
661   Purpose:
662       Compute nux, nuz with respect to x : nudx.out   if xmax!=0
663                        with respect to z : nudz.out   if zmax!=0
664               for an energy offset delta=energy
665               over Nbtour turns of the ring
666               for x varying within [-xmax, xmax] around the closed orbit
667               for z varying within [-zmax, zmax] around the closed orbit
668
669   Input:
670       Nbx    horizontal point number
671       Nbz    vertical point number
672       Nbtour turn number
673       xmax   maximum horizontal amplitude
674       zmax   maximum vertical amplitude
675       energy enrgy offset
676
677   Output:
678       none
679
680   Return:
681       none
682
683   Global variables:
684       none
685
686   Specific functions:
687       Trac_Simple, Get_NAFF
688
689   Comments:
690       16/01/03 add test for non zero frequency
691                add variation around the closed orbit
692       19/07/11 add feature to save tune shift with amplitude in the user defined file
693****************************************************************************/
694#define nterm  4
695void TunesShiftWithAmplitude(const char *NudxFile, const char *NudzFile, long Nbx, 
696                             long Nbz, long Nbtour, double xmax, double zmax, double energy)
697{
698  FILE * outf;
699  int i = 0;
700  double Tab[6][NTURN], fx[nterm], fz[nterm];
701  double x = 0.0 , xp = 0.0 , z = 0.0 , zp = 0.0;
702  double x0 = 1e-6, xp0= 0.0 , z0 = 1e-6, zp0 = 0.0;
703  double xstep = 0.0, zstep = 0.0;
704  double nux = 0.0, nuz = 0.0;
705  int nb_freq[2] = {0, 0};
706  bool stable = true;
707  struct tm *newtime;
708
709  /* Get time and date */
710  newtime = GetTime();
711
712    if (!trace) printf("\n Entering TunesShiftWithAmplitude ... results in nudx.out\n\n");
713
714    /////////////
715    // H tuneshift
716    /////////////
717
718  if (fabs(xmax) > 0.0){
719   
720    /* Opening file */
721    if ((outf = fopen(NudxFile, "w")) == NULL) {
722      fprintf(stdout, "TunesShiftWithAmplitude: error while opening file %s\n", NudxFile);
723      exit_(1);
724    }
725
726    fprintf(outf,"# Tracy III -- %s -- %s \n", NudxFile, asctime2(newtime));
727    fprintf(outf,"# nu = f(x) \n");
728    fprintf(outf,"#    x[m]          z[m]           fx            fz \n");
729
730    if ((Nbx <= 1) || (Nbz <= 1))
731      fprintf(stdout,"TunesShiftWithAmplitude: Error Nbx=%ld Nbz=%ld\n",Nbx,Nbz);
732
733    xstep = xmax/Nbx*2.0;
734    x0 = 1e-6 - xmax;
735    z0 = 1e-3;
736
737    for (i = 0; i <= Nbx; i++) {
738      x  = x0 + i*xstep ;
739      xp = xp0 ;
740      z  = z0  ;
741      zp = zp0 ;
742
743      Trac_Simple4DCOD(x,xp,z,zp,energy,0.0,Nbtour,Tab,&stable); // tracking around closed orbit
744      if (stable) {
745        Get_NAFF(nterm, Nbtour, Tab, fx, fz, nb_freq); // gets frequency vectors
746        Get_freq(fx,fz,&nux,&nuz);  // gets nux and nuz
747      }
748
749      else { // unstable
750        nux = 0.0; nuz = 0.0;
751
752      }
753      fprintf(outf,"% 10.6e % 10.6e % 10.6e % 10.6e\n",
754                    x, z, nux, nuz);
755    }
756    fclose(outf);
757  }
758
759    /////////////
760    // V tuneshift
761    /////////////
762
763  if (fabs(zmax) > 0.0)
764  {
765    /* Opening file */
766    if ((outf = fopen(NudzFile, "w")) == NULL) {
767      fprintf(stdout, "TunesShiftWithAmplitude: error while opening file %s\n", NudzFile);
768      exit_(1);
769    }
770   
771    fprintf(outf,"# tracy III -- %s -- %s \n", NudzFile, asctime2(newtime));
772    fprintf(outf,"# nu = f(z) \n");
773    fprintf(outf,"#    x[mm]         z[mm]          fx            fz \n");
774
775    zstep = zmax/Nbz*2.0;
776    x0 = 1e-3;
777    z0 = 1e-6 - zmax;
778    for (i = 0; i <= Nbz; i++) {
779      x  = x0 ;
780      xp = xp0;
781      z  = z0 + i*zstep;
782      zp = zp0;
783
784      Trac_Simple4DCOD(x,xp,z,zp,energy,0.0,Nbtour,Tab,&stable);
785      if (stable) {
786        Get_NAFF(nterm, Nbtour, Tab, fx, fz, nb_freq);
787        Get_freq(fx,fz,&nux,&nuz);  // gets nux and nuz
788      }
789      else {
790        nux = 0.0; nuz =0.0;
791      }
792      fprintf(outf,"% 10.6e % 10.6e % 10.6e % 10.6e\n",
793                    x, z, nux, nuz);
794    }
795
796    fclose(outf);
797  }
798}
799#undef nterm
800
801
802double get_D(const double df_x, const double df_y)
803{
804  double  D;
805
806  const double D_min = -2.0, D_max = -10.0;
807
808  if ((df_x != 0.0) || (df_y != 0.0))
809    D = log(sqrt(pow(df_x, 2)+pow(df_y, 2)))/log(10.0);
810  else
811    D = D_min;
812
813  return max(D, D_max);
814}
815
816
817/****************************************************************************/
818/* void fmap(const char *FmapFile, long Nbx, long Nbz, long Nbtour, double xmax, double zmax,
819          double energy, bool diffusion)
820
821   Purpose:
822       Compute a frequency map of Nbx x Nbz points
823       For each set of initial conditions the particle is tracked over
824       Nbtour for an energy offset dp
825
826       Frequency map is based on fixed beam energy, trace x versus z,
827       or, tracking transverse dynamic aperture for fixed momentum
828       (usually, on-momentum) particle.
829       
830       The stepsize follows a square root law
831
832       Results in fmap.out
833
834   Input:
835       FmapFile file to save calculated frequency map analysis
836       Nbx    horizontal step number
837       Nby    vertical step number
838       xmax   horizontal maximum amplitude
839       zmax   vertical maximum amplitude
840       Nbtour number of turn for tracking
841       energy particle energy offset
842       matlab  set file print format for matlab post-process; specific for nsrl-ii
843       
844   Output:
845       status true if stable
846              false otherwise
847
848   Return:
849       none
850
851   Global variables:
852       none
853
854   Specific functions:
855       Trac_Simple, Get_NAFF
856
857   Comments:
858       15/10/03 run for the diffusion: nasty patch for retrieving the closed orbit
859       16/02/03 patch removed
860       19/07/11 add interface of file defined by user which is used to save calculated
861                frequency map analysis
862****************************************************************************/
863#define NTERM2  10
864void fmap(const char *FmapFile, long Nbx, long Nbz, long Nbtour, double xmax, double zmax,
865          double energy, bool diffusion)         
866{
867 FILE * outf;
868 long i = 0L, j = 0L;
869 double Tab[DIM][NTURN], Tab0[DIM][NTURN];
870 double fx[NTERM2], fz[NTERM2], fx2[NTERM2], fz2[NTERM2], dfx, dfz;
871 double x = 0.0, xp = 0.0, z = 0.0, zp = 0.0;
872 double x0 = 1e-6, xp0 = 0.0, z0 = 1e-6, zp0 = 0.0;
873 const double ctau = 0.0;
874 double xstep = 0.0, zstep = 0.0;
875 double nux1 = 0.0, nuz1 = 0.0, nux2 = 0.0, nuz2 = 0.0;
876 int nb_freq[2] = {0, 0};
877 long nturn = Nbtour;
878 bool status = true;
879 struct tm *newtime;
880
881 /* Get time and date */
882 time_t aclock;
883 time(&aclock);                 /* Get time in seconds */
884 newtime = localtime(&aclock);  /* Convert time to struct */
885
886 if (trace) printf("Entering fmap ... results in %s\n\n",FmapFile);
887
888 /* Opening file */
889 if ((outf = fopen(FmapFile, "w")) == NULL) {
890   fprintf(stdout, "fmap: error while opening file %s\n", FmapFile);
891   exit_(1);
892 }
893
894 fprintf(outf,"# TRACY III -- %s -- %s \n", FmapFile, asctime2(newtime));
895 fprintf(outf,"# nu = f(x) \n");
896// fprintf(outf,"#    x[mm]          z[mm]           fx             fz"
897//       "            dfx            dfz      D=log_10(sqrt(df_x^2+df_y^2))\n");
898//
899         fprintf(outf,"#    x[m]          z[m]           fx             fz"
900         "            dfx            dfz\n");
901
902 
903 if ((Nbx < 1) || (Nbz < 1))
904   fprintf(stdout,"fmap: Error Nbx=%ld Nbz=%ld\n",Nbx,Nbz);
905 
906 // steps in both planes
907 xstep = xmax/sqrt((double)Nbx);
908 zstep = zmax/sqrt((double)Nbz);
909
910 // double number of turn if diffusion to compute
911 if (diffusion) nturn = 2*Nbtour;
912
913 // px and pz zeroed
914 xp = xp0;
915 zp = zp0;
916
917// Tracking part + NAFF
918 for (i = 0; i <= Nbx; i++) {
919 x  = x0 + sqrt((double)i)*xstep;
920// for (i = -Nbx; i <= Nbx; i++) {
921 //  x  = x0 + sgn(i)*sqrt((double)abs(i))*xstep;
922//   if (!matlab) fprintf(outf,"\n");
923   fprintf(stdout,"\n");
924   for (j = 0; j<= Nbz; j++) {
925   z  = z0 + sqrt((double)j)*zstep;
926 //  for (j = -Nbz; j<= Nbz; j++) {
927 //    z  = z0 + sgn(j)*sqrt((double)abs(j))*zstep;
928     // tracking around closed orbit
929     Trac_Simple4DCOD(x,xp,z,zp,energy,ctau,nturn,Tab,&status);
930     if (status) { // if trajectory is stable
931       // gets frequency vectors
932       Get_NAFF(NTERM2, Nbtour, Tab, fx, fz, nb_freq);
933       Get_freq(fx,fz,&nux1,&nuz1);  // gets nux and nuz
934       if (diffusion) { // diffusion
935         // shift data for second round NAFF
936         Get_Tabshift(Tab,Tab0,Nbtour,Nbtour);
937         // gets frequency vectors
938         Get_NAFF(NTERM2, Nbtour, Tab0, fx2, fz2, nb_freq);
939         Get_freq(fx2,fz2,&nux2,&nuz2); // gets nux and nuz
940       }
941     } // unstable trajectory
942     else { //zeroing output
943      nux1 = 0.0; nuz1 = 0.0;
944      nux2 = 0.0; nuz2 = 0.0;
945     }
946     
947     // printout value
948     if (!diffusion){
949//       fprintf(outf,"%14.6e %14.6e %14.6e %14.6e\n",
950//             1e3*x, 1e3*z, nux1, nuz1);
951//       fprintf(stdout,"%14.6e %14.6e %14.6e %14.6e\n",
952//             1e3*x, 1e3*z, nux1, nuz1);
953               fprintf(outf,"%10.6e %10.6e %10.6e %10.6e\n",
954               x, z, nux1, nuz1);
955       fprintf(stdout,"%14.6e %14.6e %14.6e %14.6e\n",
956               x, z, nux1, nuz1);
957     }
958     else {
959       dfx = nux1 - nux2; dfz = nuz1 - nuz2;
960//       fprintf(outf,"%14.6e %14.6e %14.6e %14.6e %14.6e %14.6e %14.6e\n",
961//             1e3*x, 1e3*z, nux1, nuz1, dfx, dfz, get_D(dfx, dfz));
962//       fprintf(stdout,"%14.6e %14.6e %14.6e %14.6e %14.6e %14.6e %14.6e\n",
963//             1e3*x, 1e3*z, nux1, nuz1, dfx, dfz, get_D(dfx, dfz));
964               fprintf(outf,"%10.6e %10.6e %10.6e %10.6e %10.6e %10.6e\n",
965               x, z, nux1, nuz1, dfx, dfz);
966       fprintf(stdout,"%14.6e %14.6e %14.6e %14.6e %14.6e %14.6e\n",
967               x, z, nux1, nuz1, dfx, dfz);
968     }
969   }
970 }
971
972 fclose(outf);
973}
974#undef NTERM2
975
976
977/****************************************************************************/
978/* void fmap_p(const char *FmapFile_p, long Nbx, long Nbz, long Nbtour, double xmax,
979               double zmax, double energy, bool diffusion, int numprocs, int myid)
980
981   Purpose:
982       Parallelized version of fmap( ).
983       Compute a frequency map of Nbx x Nbz points
984       For each set of initial conditions the particle is tracked over
985       Nbtour for an energy offset dp
986
987       Frequency map is based on fixed beam energy, trace x versus z,
988       or, tracking transverse dynamic aperture for fixed momentum
989       (usually, on-momentum) particle.
990       
991       The stepsize follows a square root law
992
993       Results in fmap.out
994
995       Input:
996       FmapFile_p   file to save calculated frequency map analysis
997       Nbx        horizontal step number
998       Nby        vertical step number
999       xmax       horizontal maximum amplitude
1000       zmax       vertical maximum amplitude
1001       Nbtour     number of turn for tracking
1002       energy     particle energy offset
1003       matlab     set file print format for matlab post-process; specific for nsrl-ii
1004       numprocs   number of processes used to do parallel computing
1005       myid      process used to do parallel computing 
1006
1007       Output:
1008       status true if stable
1009              false otherwise
1010
1011   Return:
1012       none
1013
1014   Global variables:
1015       none
1016
1017   Specific functions:
1018       Trac_Simple, Get_NAFF
1019
1020   Comments:
1021       14/11/2011 add feature to do parallel computing of frequency map analysis.
1022                  Merged with the version written by Mao-Sen Qiu at Taiwan light source.
1023****************************************************************************/
1024#define NTERM2  10
1025void fmap_p(const char *FmapFile_p, long Nbx, long Nbz, long Nbtour, double xmax, 
1026            double zmax, double energy, bool diffusion, int numprocs, int myid)   
1027{
1028 FILE * outf;
1029 long i = 0L, j = 0L;
1030 double Tab[DIM][NTURN], Tab0[DIM][NTURN];
1031 double fx[NTERM2], fz[NTERM2], fx2[NTERM2], fz2[NTERM2], dfx, dfz;
1032 double x = 0.0, xp = 0.0, z = 0.0, zp = 0.0;
1033 double x0 = 1e-6, xp0 = 0.0, z0 = 1e-6, zp0 = 0.0;
1034 const double ctau = 0.0;
1035 double xstep = 0.0, zstep = 0.0;
1036 double nux1 = 0.0, nuz1 = 0.0, nux2 = 0.0, nuz2 = 0.0;
1037 int nb_freq[2] = {0, 0};
1038 long nturn = Nbtour;
1039 bool status = true;
1040 struct tm *newtime;
1041
1042 char FmapFile[max_str];
1043 sprintf(FmapFile,"%d",myid);
1044 strcat(FmapFile,FmapFile_p);
1045 printf("%s\n",FmapFile);
1046
1047 /* Get time and date */
1048 time_t aclock;
1049 time(&aclock);                 /* Get time in seconds */
1050 newtime = localtime(&aclock);  /* Convert time to struct */
1051
1052 if (trace) printf("Entering fmap ... results in %s\n\n",FmapFile);
1053
1054 /* Opening file */
1055 if ((outf = fopen(FmapFile, "w")) == NULL)
1056 {
1057   fprintf(stdout, "fmap: error while opening file %s\n", FmapFile);
1058   exit_(1);
1059 }
1060
1061 if(myid==0)
1062 {
1063  fprintf(outf,"# TRACY III -- %s -- %s \n", FmapFile_p, asctime2(newtime));
1064  fprintf(outf,"# nu = f(x) \n");
1065  fprintf(outf,"#    x[m]          z[m]           fx             fz            dfx            dfz\n");
1066 }
1067 
1068 if ((Nbx < 1) || (Nbz < 1))
1069   fprintf(stdout,"fmap: Error Nbx=%ld Nbz=%ld\n",Nbx,Nbz);
1070 
1071 // steps in both planes
1072 xstep = xmax/sqrt((double)Nbx);
1073 zstep = zmax/sqrt((double)Nbz);
1074
1075 // double number of turn if diffusion to compute
1076 if (diffusion) nturn = 2*Nbtour;
1077
1078 // px and pz zeroed
1079 xp = xp0;
1080 zp = zp0;
1081
1082// Tracking part + NAFF
1083//for (i = 0; i< Nbx; i++)
1084//Each core or process calculate different region of fmap according to id number. MSChiu 2011/10/13
1085int deb,fin;
1086 int integer,residue;
1087 integer=((int)Nbx)/numprocs;
1088 residue=((int)Nbx)-integer*numprocs;
1089
1090 printf("myid:%d, integer:%d, residue:%d, numprocs:%d, Nbx:%d\n\n",myid,integer,residue,numprocs,Nbx);
1091
1092 //split tracking region (x,z) for each process
1093 if(myid<residue)
1094 {
1095  deb=myid*(integer+1);
1096  fin=(myid+1)*(integer+1);
1097 }
1098 else
1099 {
1100  deb=residue*(integer+1)+(myid-residue)*integer;
1101  fin=residue*(integer+1)+(myid+1-residue)*integer;
1102 }
1103
1104 // tracking and FFT, and get the tunes for each particle starts from (x,z)
1105 for (i = deb; i < fin; i++)
1106 {
1107   x  = x0 + sqrt((double)i)*xstep;
1108
1109   fprintf(stdout,"\n");
1110   for (j = 0; j< Nbz; j++) 
1111   {
1112     z  = z0 + sqrt((double)j)*zstep;
1113 
1114     // tracking around closed orbit
1115     Trac_Simple4DCOD(x,xp,z,zp,energy,ctau,nturn,Tab,&status);
1116     if (status) // if trajectory is stable
1117     { 
1118       // gets frequency vectors
1119       Get_NAFF(NTERM2, Nbtour, Tab, fx, fz, nb_freq);
1120       Get_freq(fx,fz,&nux1,&nuz1);  // gets nux and nuz
1121       if (diffusion)
1122       { // diffusion
1123         // shift data for second round NAFF
1124         Get_Tabshift(Tab,Tab0,Nbtour,Nbtour);
1125         // gets frequency vectors
1126         Get_NAFF(NTERM2, Nbtour, Tab0, fx2, fz2, nb_freq);
1127         Get_freq(fx2,fz2,&nux2,&nuz2); // gets nux and nuz
1128        }
1129     } // unstable trajectory
1130     else
1131     { //zeroing output
1132      nux1 = 0.0; nuz1 = 0.0;
1133      nux2 = 0.0; nuz2 = 0.0;
1134     }
1135     
1136     // printout value
1137     if (!diffusion)
1138     {
1139     fprintf(outf,"%10.6e %10.6e %10.6e %10.6e\n",x, z, nux1, nuz1);
1140     fprintf(stdout,"%14.6e %14.6e %14.6e %14.6e\n",x, z, nux1, nuz1);
1141     }
1142     else
1143     {
1144     dfx = nux1 - nux2;
1145     dfz = nuz1 - nuz2;
1146
1147     fprintf(outf,"%10.6e %10.6e %10.6e %10.6e %10.6e %10.6e\n", x, z, nux1, nuz1, dfx, dfz);
1148     fprintf(stdout,"%14.6e %14.6e %14.6e %14.6e %14.6e %14.6e\n", x, z, nux1, nuz1, dfx, dfz);
1149     }
1150   }
1151 }
1152
1153 fclose(outf);
1154}
1155#undef NTERM2
1156
1157
1158
1159/****************************************************************************/
1160/* void fmapdp(const char *FmapdpFile, long Nbx, long Nbe, long Nbtour, double xmax, double emax,
1161              double z, bool diffusion)
1162
1163   Purpose:
1164       Compute a frequency map of Nbx x Nbz points
1165       For each set of initial conditions the particle is tracked over
1166       Nbtour for an energy offset dp
1167       
1168       Frequency map is based on fixed vertical amplitude z, trace x versus energy,
1169       or, tracking x for off-momentum particle.
1170           
1171       The stepsize follows a square root law
1172
1173       Results in fmapdp.out
1174
1175   Input:
1176       FmapdpFile       file to save calculated frequency map analysis
1177       Nbx              horizontal step number
1178       Nbe              energy step number
1179       Nbtour           number of turns for tracking
1180       xmax             horizontal maximum amplitude
1181       emax             maximum energy
1182       z                vertical amplitude
1183       diffusion        flag to calculate tune diffusion
1184       matlab  set file print format for matlab post-process; specific for nsrl-ii
1185   Output:
1186       status true if stable
1187              false otherwise
1188
1189   Return:
1190       none
1191
1192   Global variables:
1193       none
1194
1195   Specific functions:
1196       Trac_Simple, Get_NAFF
1197
1198   Comments:
1199       15/10/03 run for the diffusion: nasty patch for retrieving the closed orbit
1200       23/10/04 for 6D turn off diffusion automatically and horizontal amplitude
1201       is negative for negative enrgy offset since this is true for the cod
1202       19/07/11  add features to save calculated fmapdp in the user defined file
1203****************************************************************************/
1204#define NTERM2  10
1205void fmapdp(const char *FmapdpFile, long Nbx, long Nbe, long Nbtour, double xmax, double emax,
1206              double z, bool diffusion)
1207{
1208 FILE * outf;
1209 long i = 0L, j = 0L;
1210 double Tab[DIM][NTURN], Tab0[DIM][NTURN];
1211 double fx[NTERM2], fz[NTERM2], fx2[NTERM2], fz2[NTERM2], dfx, dfz;
1212 double x = 0.0, xp = 0.0, zp = 0.0, dp = 0.0, ctau = 0.0;
1213 double x0 = 1e-6, xp0 = 0.0, zp0 = 0.0;
1214 double xstep = 0.0, estep = 0.0;
1215 double nux1 = 0.0, nuz1 = 0.0, nux2 = 0.0, nuz2 = 0.0;
1216 
1217 int nb_freq[2] = {0, 0};
1218 long nturn = Nbtour;
1219 bool status=true;
1220 struct tm *newtime;
1221
1222 /* Get time and date */
1223 time_t aclock;
1224 time(&aclock);                 /* Get time in seconds */
1225 newtime = localtime(&aclock);  /* Convert time to struct */
1226
1227 if (diffusion && globval.Cavity_on == false) nturn = 2*Nbtour;
1228
1229 if (trace) printf("Entering fmap ... results in %s\n\n",FmapdpFile);
1230
1231 /* Opening file */
1232 if ((outf = fopen(FmapdpFile, "w")) == NULL) {
1233   fprintf(stdout, "fmapdp: error while opening file %s\n", FmapdpFile);
1234   exit_(1);
1235 }
1236
1237 fprintf(outf,"# TRACY III -- %s -- %s \n", FmapdpFile, asctime2(newtime));
1238 fprintf(outf,"# nu = f(x) \n");
1239// fprintf(outf,"#    dp[%%]         x[mm]          fx            fz           dfx           dfz\n");
1240fprintf(outf,"#    dp[m]         x[m]           fx            fz           dfx           dfz\n");
1241 
1242 if ((Nbx <= 1) || (Nbe <= 1))
1243   fprintf(stdout,"fmapdp: Error Nbx=%ld Nbe=%ld\n",Nbx,Nbe);
1244
1245 xp = xp0;
1246 zp = zp0;
1247
1248 xstep = xmax/sqrt((double)Nbx);
1249 estep = 2.0*emax/Nbe;
1250
1251 for (i = 0; i <= Nbe; i++) {
1252   dp  = -emax + i*estep;
1253//   if (!matlab) fprintf(outf,"\n");
1254   fprintf(stdout,"\n");
1255   for (j = 0; j<= Nbx; j++) {
1256//   for (j = -Nbx; j<= Nbx; j++) {
1257
1258     // IF 6D Tracking diffusion turn off and x negative for dp negative
1259     if ((globval.Cavity_on == true) && (dp < 0.0)){
1260    //   x  = x0 - sgn(j)*sqrt((double)abs(j))*xstep;
1261         x  = x0 - sqrt((double)j)*xstep;
1262        diffusion = false;
1263     }   
1264     else
1265      // x  = x0 + sgn(j)*sqrt((double)abs(j))*xstep;
1266         x  = x0 + sqrt((double)j)*xstep;
1267     Trac_Simple4DCOD(x,xp,z,zp,dp,ctau,nturn,Tab,&status);
1268     if (status) {
1269       Get_NAFF(NTERM2, Nbtour, Tab, fx, fz, nb_freq);
1270       Get_freq(fx,fz,&nux1,&nuz1);  // gets nux and nuz
1271       if (diffusion) { // diffusion
1272         Get_Tabshift(Tab,Tab0,Nbtour,Nbtour); // shift data for second round NAFF
1273         Get_NAFF(NTERM2, Nbtour, Tab0, fx2, fz2, nb_freq); // gets frequency vectors
1274         Get_freq(fx2,fz2,&nux2,&nuz2); // gets nux and nuz
1275       }
1276     } // unstable trajectory       
1277     else { //zeroing output
1278      nux1 = 0.0; nuz1 = 0.0;
1279      nux2 = 0.0; nuz2 = 0.0;
1280     }
1281
1282     // printout value
1283     if (!diffusion){
1284//       fprintf(outf,"%14.6e %14.6e %14.6e %14.6e\n",
1285//             1e2*dp, 1e3*x, nux1, nuz1);
1286//       fprintf(stdout,"%14.6e %14.6e %14.6e %14.6e\n",
1287//             1e2*dp, 1e3*x, nux1, nuz1);
1288        fprintf(outf,"% 10.6e % 10.6e % 10.6e % 10.6e\n", dp, x, nux1, nuz1);
1289       fprintf(stdout,"% 10.6e % 10.6e % 10.6e % 10.6e\n", dp, x, nux1, nuz1);
1290     }
1291     else {
1292       dfx = nux2 - nux1; dfz = nuz2 - nuz1;
1293//       fprintf(outf,"%14.6e %14.6e %14.6e %14.6e %14.6e %14.6e %14.6e\n",
1294//             1e2*dp, 1e3*x, nux1, nuz2, dfx, dfz, get_D(dfx, dfz));
1295//       fprintf(stdout,"%14.6e %14.6e %14.6e %14.6e %14.6e %14.6e %14.6e\n",
1296//             1e2*dp, 1e3*x, nux1, nuz2, dfx, dfz, get_D(dfx, dfz));
1297     fprintf(outf,"% 10.6e % 10.6e % 10.6e % 10.6e % 10.6e % 10.6e\n",
1298        dp, x, nux1, nuz2, dfx, dfz);
1299       fprintf(stdout,"% 10.6e % 10.6e % 10.6e % 10.6e % 10.6e % 10.6e\n",
1300        dp, x, nux1, nuz2, dfx, dfz);
1301     }
1302   }
1303 }
1304
1305 fclose(outf);
1306}
1307#undef NTERM2
1308
1309/****************************************************************************/
1310/* void fmapdp_p(const char *FmapdpFile_p, long Nbx, long Nbe, long Nbtour,double xmax,
1311                 double emax, double z, bool diffusion, int numprocs, int myid)
1312   
1313
1314   Purpose:
1315       Parallel version of fmapdp( ).
1316       Compute a frequency map of Nbx x Nbz points
1317       For each set of initial conditions the particle is tracked over
1318       Nbtour for an energy offset dp
1319       
1320       Frequency map is based on fixed vertical amplitude z, trace x versus energy,
1321       or, tracking x for off-momentum particle.
1322           
1323       The stepsize follows a square root law
1324
1325       Results in fmapdp.out
1326       
1327  Input:
1328       FmapdpFile_p       file to save calculated frequency map analysis
1329       Nbx              horizontal step number
1330       Nbe              energy step number
1331       Nbtour           number of turns for tracking
1332       xmax             horizontal maximum amplitude
1333       emax             maximum energy
1334       z                vertical amplitude
1335       diffusion        flag to calculate tune diffusion
1336       numprocs         Number of processes used to do parallel computing
1337       myid             process used to do parallel computing     
1338
1339   Output:
1340       status true if stable
1341              false otherwise
1342
1343   Return:
1344       none
1345
1346   Global variables:
1347       none
1348
1349   Specific functions:
1350       Trac_Simple, Get_NAFF
1351
1352   Comments:
1353       14/11/2011  add features to parallel calculate fmapdp.
1354                   Merged with the version written by Mao-sen Qiu at Taiwan light source.
1355****************************************************************************/
1356#define NTERM2  10
1357void fmapdp_p(const char *FmapdpFile_p, long Nbx, long Nbe, long Nbtour, double xmax, 
1358              double emax, double z, bool diffusion, int numprocs, int myid)
1359{
1360 FILE * outf;
1361 long i = 0L, j = 0L;
1362 double Tab[DIM][NTURN], Tab0[DIM][NTURN];
1363 double fx[NTERM2], fz[NTERM2], fx2[NTERM2], fz2[NTERM2], dfx, dfz;
1364 double x = 0.0, xp = 0.0, zp = 0.0, dp = 0.0, ctau = 0.0;
1365 double x0 = 1e-6, xp0 = 0.0, zp0 = 0.0;
1366 double xstep = 0.0, estep = 0.0;
1367 double nux1 = 0.0, nuz1 = 0.0, nux2 = 0.0, nuz2 = 0.0;
1368 
1369 int nb_freq[2] = {0, 0};
1370 long nturn = Nbtour;
1371 bool status=true;
1372 struct tm *newtime;
1373
1374char FmapdpFile[max_str];
1375 sprintf(FmapdpFile,"%d",myid);
1376 strcat(FmapdpFile,FmapdpFile_p);
1377 printf("%s\n",FmapdpFile);
1378
1379 /* Get time and date */
1380 time_t aclock;
1381 time(&aclock);                 /* Get time in seconds */
1382 newtime = localtime(&aclock);  /* Convert time to struct */
1383
1384 if (diffusion && globval.Cavity_on == false) nturn = 2*Nbtour;
1385
1386 if (trace) printf("Entering fmap ... results in %s\n\n",FmapdpFile);
1387
1388 /* Opening file */
1389 if ((outf = fopen(FmapdpFile, "w")) == NULL) {
1390   fprintf(stdout, "fmapdp: error while opening file %s\n", FmapdpFile);
1391   exit_(1);
1392 }
1393
1394 if(myid==0)
1395   {
1396     fprintf(outf,"# TRACY III -- %s -- %s \n", FmapdpFile_p, asctime2(newtime));
1397     fprintf(outf,"# nu = f(x) \n");
1398     // fprintf(outf,"#    dp[%%]         x[mm]          fx            fz           dfx           dfz\n");
1399     fprintf(outf,"#    dp[m]         x[m]           fx            fz           dfx           dfz\n");
1400   }
1401 
1402if ((Nbx <= 1) || (Nbe <= 1))
1403   fprintf(stdout,"fmapdp: Error Nbx=%ld Nbe=%ld\n",Nbx,Nbe);
1404
1405 xp = xp0;
1406 zp = zp0;
1407
1408 xstep = xmax/sqrt((double)Nbx);
1409 estep = 2.0*emax/Nbe;
1410
1411// for (i = 0; i < Nbe; i++)
1412// Eace core or process calculate different region of fmapdp according to id number. MSChiu 2011/10/13
1413 int deb,fin;
1414 int integer,residue;
1415 integer=((int)Nbe)/numprocs;
1416 residue=((int)Nbe)-integer*numprocs;
1417
1418 printf("myid:%d, integer:%d, resideu:%d, numprocs:%d, Nbe:%d\n\n",myid,integer,residue,numprocs,Nbe);
1419
1420 //split tracking region for each process
1421 if(myid<residue)
1422 {
1423  deb=myid*(integer+1);
1424  fin=(myid+1)*(integer+1);
1425 }
1426 else
1427 {
1428  deb=residue*(integer+1)+(myid-residue)*integer;
1429  fin=residue*(integer+1)+(myid+1-residue)*integer;
1430 }
1431
1432 //begin tracking and FFT, and get tunes for the particle starts from (x,p)
1433 for (i = deb; i < fin; i++)
1434 {
1435   dp  = -emax + i*estep;
1436
1437   // for (i = 0; i <= Nbe; i++) {
1438   // dp  = -emax + i*estep;
1439//   if (!matlab) fprintf(outf,"\n");
1440   fprintf(stdout,"\n");
1441   for (j = 0; j<= Nbx; j++) {
1442//   for (j = -Nbx; j<= Nbx; j++) {
1443
1444     // IF 6D Tracking diffusion turn off and x negative for dp negative
1445     if ((globval.Cavity_on == true) && (dp < 0.0)){
1446    //   x  = x0 - sgn(j)*sqrt((double)abs(j))*xstep;
1447         x  = x0 - sqrt((double)j)*xstep;
1448        diffusion = false;
1449     }   
1450     else
1451      // x  = x0 + sgn(j)*sqrt((double)abs(j))*xstep;
1452         x  = x0 + sqrt((double)j)*xstep;
1453     Trac_Simple4DCOD(x,xp,z,zp,dp,ctau,nturn,Tab,&status);
1454     if (status) {
1455       Get_NAFF(NTERM2, Nbtour, Tab, fx, fz, nb_freq);
1456       Get_freq(fx,fz,&nux1,&nuz1);  // gets nux and nuz
1457       if (diffusion) { // diffusion
1458         Get_Tabshift(Tab,Tab0,Nbtour,Nbtour); // shift data for second round NAFF
1459         Get_NAFF(NTERM2, Nbtour, Tab0, fx2, fz2, nb_freq); // gets frequency vectors
1460         Get_freq(fx2,fz2,&nux2,&nuz2); // gets nux and nuz
1461       }
1462     } // unstable trajectory       
1463     else { //zeroing output
1464      nux1 = 0.0; nuz1 = 0.0;
1465      nux2 = 0.0; nuz2 = 0.0;
1466     }
1467
1468     // printout value
1469     if (!diffusion){
1470//       fprintf(outf,"%14.6e %14.6e %14.6e %14.6e\n",
1471//             1e2*dp, 1e3*x, nux1, nuz1);
1472//       fprintf(stdout,"%14.6e %14.6e %14.6e %14.6e\n",
1473//             1e2*dp, 1e3*x, nux1, nuz1);
1474        fprintf(outf,"% 10.6e % 10.6e % 10.6e % 10.6e\n", dp, x, nux1, nuz1);
1475       fprintf(stdout,"% 10.6e % 10.6e % 10.6e % 10.6e\n", dp, x, nux1, nuz1);
1476     }
1477     else {
1478       dfx = nux2 - nux1; dfz = nuz2 - nuz1;
1479//       fprintf(outf,"%14.6e %14.6e %14.6e %14.6e %14.6e %14.6e %14.6e\n",
1480//             1e2*dp, 1e3*x, nux1, nuz2, dfx, dfz, get_D(dfx, dfz));
1481//       fprintf(stdout,"%14.6e %14.6e %14.6e %14.6e %14.6e %14.6e %14.6e\n",
1482//             1e2*dp, 1e3*x, nux1, nuz2, dfx, dfz, get_D(dfx, dfz));
1483     fprintf(outf,"% 10.6e % 10.6e % 10.6e % 10.6e % 10.6e % 10.6e\n",
1484        dp, x, nux1, nuz2, dfx, dfz);
1485       fprintf(stdout,"% 10.6e % 10.6e % 10.6e % 10.6e % 10.6e % 10.6e\n",
1486        dp, x, nux1, nuz2, dfx, dfz);
1487     }
1488   }
1489 }
1490
1491 fclose(outf);
1492}
1493#undef NTERM2
1494
1495
1496/****************************************************************************/
1497/* void TunesShiftWithEnergy(long Nb, long Nbtour, double emax)
1498
1499   Purpose:
1500       Computes tunes versus energy offset by tracking
1501       by linear energy step between -emax and emax
1502
1503   Input:
1504       Nb+1   numbers of points
1505       NbTour number of turns for tracking
1506       emax   maximum energy
1507
1508   Output:
1509       none
1510
1511   Return:
1512       none
1513
1514   Global variables:
1515       trace
1516
1517   Specific functions:
1518       Trac_Simple, Get_NAFF
1519
1520   Comments:
1521       none
1522
1523****************************************************************************/
1524#define NTERM  4
1525void TunesShiftWithEnergy(const char *NudpFile,long Nb, long Nbtour, double emax)
1526{
1527  FILE * outf;
1528 
1529  long i = 0L;
1530//  long lastpos = 0L;
1531  double Tab[DIM][NTURN];
1532  double fx[NTERM], fz[NTERM];
1533  double x  = 0.0,  xp  = 0.0, z  = 0.0,  zp  = 0.0, ctau  = 0.0, dp  = 0.0;
1534  double x0 = 1e-6, xp0 = 0.0, z0 = 1e-6, zp0 = 0.0, ctau0 = 0.0, dp0 = 0.0;
1535  double nux1 = 0.0, nuz1 = 0.0;
1536  int nb_freq[2] = {0, 0};
1537  bool status = true;
1538  struct tm *newtime;
1539
1540  /* Get time and date */
1541  newtime = GetTime();
1542
1543  if (!trace) printf("\n Entering TunesShiftWithEnergy ...\n\n");
1544
1545  /* Opening file */
1546  if ((outf = fopen(NudpFile, "w")) == NULL) {
1547    fprintf(stdout, "NuDp: error while opening file %s\n", NudpFile);
1548    exit_(1);
1549  }
1550
1551  fprintf(outf,"# TRACY III -- %s -- %s \n", NudpFile, asctime2(newtime));
1552  fprintf(outf,"#    dP/P           fx            fz          xcod         pxcod          zcod         pzcod\n");
1553  if (trace) fprintf(stdout,"#    dP/P           fx            fz          xcod         pxcod          zcod         pzcod\n");
1554
1555  if (Nb <= 1L)
1556    fprintf(stdout,"NuDp: Error Nb=%ld\n",Nb);
1557
1558  // start loop over energy 
1559  dp0 = -emax;
1560
1561  for (i = 0L; i < Nb; i++) {
1562    dp   = dp0 + i*emax/(Nb-1)*2;
1563    x    = x0  ;
1564    xp   = xp0 ;
1565    z    = z0  ;
1566    zp   = zp0 ;
1567    ctau = ctau0;
1568   
1569    Trac_Simple4DCOD(x,xp,z,zp,dp,ctau,Nbtour,Tab,&status); // tracking around closed orbit
1570    if (status) {
1571       Get_NAFF(NTERM, Nbtour, Tab, fx, fz, nb_freq); // get frequency vectors
1572       Get_freq(fx,fz,&nux1,&nuz1);  // gets nux and nuz
1573    }
1574    else {
1575       nux1 = 0.0; nuz1 = 0.0;
1576       status = true;
1577    }
1578   
1579    long lastpos=0L;
1580    getcod(dp, lastpos); // get cod for printout
1581
1582
1583    fprintf(outf,"%14.6e %14.6e %14.6e %14.6e %14.6e %14.6e %14.6e\n",
1584            dp, nux1,nuz1, globval.CODvect[0], globval.CODvect[1],
1585            globval.CODvect[2], globval.CODvect[3]);
1586
1587    if (trace) fprintf(stdout,"%14.6e %14.6e %14.6e %14.6e %14.6e %14.6e %14.6e\n",
1588            dp, nux1,nuz1, globval.CODvect[0], globval.CODvect[1],
1589            globval.CODvect[2], globval.CODvect[3]);
1590  }
1591
1592  fclose(outf);
1593}
1594#undef NTERM
1595
1596
1597
1598
1599/****************************************************************************/
1600/* void Phase(double x,double xp,double y, double yp,double energy, double ctau, long Nbtour)
1601
1602   Purpose:
1603       Compute 6D phase space
1604       Results in phase.out
1605
1606   Input:
1607       x, xp, y, yp, energy, ctau starting position
1608       Nbtour turn number
1609
1610   Output:
1611       none
1612
1613   Return:
1614       none
1615
1616   Global variables:
1617       trace
1618
1619   Specific functions:
1620       Trac_Simple6DCOD, Get_NAFF
1621
1622   Comments:
1623       1 December 2010, Call to a Tracking round around the 6D and not 4D closed orbit
1624
1625****************************************************************************/
1626void Phase(const char *phasefile, double x,double xp,double y, double yp,double energy, double ctau, long Nbtour)
1627{
1628  double Tab[6][NTURN];
1629  FILE *outf;
1630  const char *fic = phasefile; 
1631  int i;
1632  bool status;
1633  struct tm *newtime;
1634
1635  /* Get time and date */
1636  newtime = GetTime();
1637   
1638 
1639 
1640  if (Nbtour > NTURN) {
1641    fprintf(stdout, "Phase: error Nbtour=%ld > NTURN=%d\n",Nbtour,NTURN);
1642    exit_(1);
1643  }
1644
1645  if ((outf = fopen(fic, "w")) == NULL)  {
1646    fprintf(stdout, "Phase: error while opening file %s\n", fic);
1647    exit_(1);
1648  }
1649
1650  fprintf(outf,"# TRACY III -- %s -- %s \n", fic, asctime2(newtime));
1651  fprintf(outf,"# Phase Space \n");
1652  fprintf(outf,
1653  "#    x           xp             z            zp           dp          ctau\n");
1654
1655  // initialization to zero (case where unstable
1656  for (i = 0; i < Nbtour; i++) {
1657    Tab[0][i] = 0.0;
1658    Tab[1][i] = 0.0;
1659    Tab[2][i] = 0.0;
1660    Tab[3][i] = 0.0;
1661    Tab[4][i] = 0.0;
1662    Tab[5][i] = 0.0;
1663  }
1664 
1665  Trac_Simple6DCOD(x,xp,y,yp,energy,ctau,Nbtour,Tab,&status);
1666  for (i = 0; i < Nbtour; i++) {
1667    fprintf(outf,"% .5e % .5e % .5e % .5e % .5e % .5e\n",
1668            Tab[0][i],Tab[1][i],Tab[2][i],Tab[3][i],Tab[4][i],Tab[5][i]);
1669  }
1670  fclose(outf);
1671}
1672
1673/****************************************************************************/
1674/* void PhasePoly(long pos, double x0,double px0, double z0, double pz0, double delta0,
1675               double ctau0, long Nbtour)
1676
1677   Purpose:
1678       Compute 6D phase space at position pos (=element number in the lattice )
1679       for several particles: first aim was for injection study
1680       Results in phasepoly.out
1681
1682   Input:
1683       x, xp, y, yp, energy, ctau starting position
1684       Nbtour turn number
1685
1686   Output:
1687       none
1688
1689   Return:
1690       none
1691
1692   Global variables:
1693       trace
1694
1695   Specific functions:
1696       Trac_Simple, Get_NAFF
1697
1698   Comments:
1699       none
1700
1701****************************************************************************/
1702void PhasePoly(long pos, double x0,double px0, double z0, double pz0, double delta0,
1703               double ctau0, long Nbtour)
1704{
1705  FILE *outf;
1706  const char  *fic="phasepoly.out";
1707  long        lastpos = 0,lastn = 0;
1708  int         i,j;
1709  double      x, z, px, pz, delta, ctau;
1710  double      ex = 1368E-9, el = 1.78E-4;
1711  double      betax = 9.0, /*betaz = 8.2, */betal = 45.5;
1712  Vector      xsynch;
1713  int         nx = 1, ne = 400;
1714  struct tm   *newtime;
1715
1716  /* Get time and date */
1717  newtime = GetTime();
1718
1719  fprintf(stdout,"Closed orbit:\n");
1720  fprintf(stdout,"      x            px           z           pz        delta       ctau\n");
1721  fprintf(stdout,"% 12.8f % 12.8f % 12.8f % 12.8f % 12.8f % 12.8f\n",
1722          globval.CODvect[0], globval.CODvect[1], globval.CODvect[2],
1723          globval.CODvect[3], globval.CODvect[4], globval.CODvect[5]);
1724  lastpos = pos;
1725  globval.CODvect = xsynch;
1726//  xsynch[0] = globval.CODvect[0];
1727//  xsynch[1] = globval.CODvect[1];
1728//  xsynch[2] = globval.CODvect[2];
1729//  xsynch[3] = globval.CODvect[3];
1730//  xsynch[4] = globval.CODvect[4];
1731//  xsynch[5] = globval.CODvect[5];
1732 
1733  if ((outf = fopen(fic, "w")) == NULL)  {
1734    fprintf(stdout, "Phase: error while opening file %s\n", fic);
1735    exit_(1);
1736  }
1737
1738  fprintf(outf,"# TRACY III -- %s -- %s \n", fic, asctime2(newtime));
1739  fprintf(outf,"# 6D Phase Space \n");
1740  fprintf(outf,
1741  "# num         x           xp             z            zp           dp          ctau\n");
1742
1743  trace = true;
1744  for (j = 0; j < ne; j++){
1745    for (i = 0; i < nx; i++){
1746       x     = x0     + xsynch[0] + sqrt(ex*betax)*cos(2.0*M_PI/nx*i)*0;
1747       px    = px0    + xsynch[1] + sqrt(ex/betax)*sin(2.0*M_PI/nx*i)*0;
1748       z     = z0     + xsynch[2];
1749       pz    = pz0    + xsynch[3];
1750       delta = delta0 + xsynch[4] + sqrt(el/betal)*sin(2*M_PI/ne*j)*0 ;
1751       ctau  = ctau0  + xsynch[5] + sqrt(el*betal)*cos(2*M_PI/ne*j)*0 + j*0.002;
1752       fprintf(outf, "%6ld %+10.5e %+10.5e %+10.5e %+10.5e %+10.5e %+10.5e",
1753                      0L, x, px, z, pz, delta, ctau);
1754       Trac(x,px,z,pz,delta,ctau, Nbtour,pos, lastn, lastpos, outf);
1755       fprintf(outf,"\n");
1756    }
1757  }
1758  fclose(outf);
1759}
1760
1761/****************************************************************************/
1762/* void PhasePortrait(double x0,double px0,double z0, double pz0, double delta0,
1763                   double end, double Nb, long Nbtour, int num)
1764
1765   Purpose:
1766       Compute a phase portrait: Nb orbits
1767       Results in phaseportrait.out
1768
1769   Input:
1770       x0, px0, z0, Pz0, delta0, starting position
1771       num cooordinate to vary (0 is x and 4 is delta)
1772       end is the last value for the varying coordinate
1773       Nb is the number of orbits to draw
1774       Nbtour turn number
1775
1776   Output:
1777       none
1778
1779   Return:
1780       none
1781
1782   Global variables:
1783       none
1784
1785   Specific functions:
1786       Trac_Simple
1787
1788   Comments:
1789       Change of tracking routine: do not use a tabular to store data
1790
1791****************************************************************************/
1792void PhasePortrait(double x0,double px0,double z0, double pz0, double delta0,
1793                   double ctau0, double end, long Nb, long Nbtour, int num)
1794{
1795  double Tab[6][NTURN];
1796  FILE *outf;
1797  const char fic[] = "phaseportrait.out";
1798  int i = 0, j = 0;
1799  double start = 0.0, step = 0.0;
1800  double x = 0.0, px = 0.0, z = 0.0, pz = 0.0, delta = 0.0, ctau = 0.0;
1801  bool status = true;
1802  struct tm *newtime;
1803
1804  /* Get time and date */
1805  newtime = GetTime();
1806
1807  if (Nbtour > NTURN) {
1808    fprintf(stdout, "Phase: error Nbtour=%ld > NTURN=%d\n",Nbtour,NTURN);
1809    exit_(1);
1810  }
1811
1812  if ((outf = fopen(fic, "w")) == NULL) {
1813    fprintf(stdout, "Phase: error while opening file %s\n", fic);
1814    exit_(1);
1815  }
1816
1817  fprintf(outf,"# TRACY III  -- %s \n", asctime2(newtime));
1818  fprintf(outf,"#  x           xp            z           zp           dp          ctau\n#\n");
1819 
1820  x = x0; px = px0;
1821  z = z0; pz = pz0;
1822  delta = delta0; 
1823 
1824  switch (num) {
1825    case 0:
1826      start = x0; break;
1827    case 1:
1828      start = px0; break;
1829    case 2:
1830      start = z0; break;
1831    case 3:
1832      start = pz0; break;
1833    case 4:
1834      start = delta0; break;
1835    case 5:
1836      start = ctau0; break;
1837  }
1838
1839  /** Step between initial conditions **/
1840  step = (end - start)/Nb;
1841
1842  for (j = 0; j <= Nb; j++){
1843    switch (num){
1844      case 0:
1845        x     = start + j*step;  break;
1846      case 1:
1847        px    = start + j*step;  break;
1848      case 2:
1849        z     = start + j*step;  break;
1850      case 3:
1851        pz    = start + j*step;  break;
1852      case 4:
1853        delta = start + j*step;  break;
1854      case 5:
1855        ctau  = start + j*step;  break;
1856    }
1857
1858   fprintf(stdout,"% .5e % .5e % .5e % .5e % .5e % .5e\n",
1859            x,px,z,pz,delta,ctau);
1860    Trac_Simple4DCOD(x,px,z,pz,delta,ctau,Nbtour,Tab,&status);
1861   for (i = 0; i < Nbtour; i++) {
1862      fprintf(outf,"% .5e % .5e % .5e % .5e % .5e % .5e\n",
1863            Tab[0][i],Tab[1][i],Tab[2][i],Tab[3][i],Tab[4][i],Tab[5][i]);
1864    }
1865  }
1866  fclose(outf);
1867}
1868
1869
1870/****************************************************************************/
1871/* void Check_Trac(double x, double px, double y, double py, double dp)
1872
1873   Purpose:
1874       Diagnosis for tracking
1875       Used only for debuging
1876       Print particle coordinates after each element over 1 single turn
1877
1878   Input:
1879       x, px, y, py, dp starting conditions for tracking
1880
1881   Output:
1882       none
1883
1884   Return:
1885       none
1886
1887   Global variables:
1888       trace
1889
1890   Specific functions:
1891       Trac_Simple, Get_NAFF
1892
1893   Comments:
1894       none
1895
1896****************************************************************************/
1897void Check_Trac(double x, double px, double y, double py, double dp)
1898{
1899  Vector x1;             /* Tracking coordinates */
1900  long lastpos = globval.Cell_nLoc;
1901  FILE *outf;
1902  const char fic[] = "check_ampl.out";
1903  int i;
1904
1905  if ((outf = fopen(fic, "w")) == NULL)
1906  {
1907    fprintf(stdout, "Phase: error while opening file %s\n", fic);
1908    exit_(1);
1909  }
1910
1911  x1[0] =  x; x1[1] = px;
1912  x1[2] =  y; x1[3] = py;
1913  x1[4] = dp; x1[5] = 0e0;
1914
1915  fprintf(outf,"# i    x   xp  z   zp   delta cT \n");
1916
1917  for (i = 1; i<= globval.Cell_nLoc; i++)
1918  {
1919    Cell_Pass(i,i+1, x1, lastpos);
1920    fprintf(outf,"%4d % .5e % .5e % .5e % .5e % .5e % .5e\n",
1921            i, x1[0],x1[1],x1[2],x1[3],x1[4],x1[5]);
1922  }
1923}
1924
1925/****************************************************************************/
1926/* void Enveloppe(double x, double px, double y, double py, double dp, double nturn)
1927
1928   Purpose:
1929       Diagnosis for tracking
1930       Used only for debuging
1931       Print particle coordinates after each element over 1 single turn
1932
1933   Input:
1934       x, px, y, py, dp starting conditions for tracking
1935
1936   Output:
1937       none
1938
1939   Return:
1940       none
1941
1942   Global variables:
1943       trace
1944
1945   Specific functions:
1946       Trac_Simple, Get_NAFF
1947
1948   Comments:
1949       none
1950
1951****************************************************************************/
1952void Enveloppe(double x, double px, double y, double py, double dp, double nturn)
1953{
1954  Vector x1; /* Tracking coordinates */
1955  long lastpos = globval.Cell_nLoc;
1956  FILE *outf;
1957  const char fic[] = "enveloppe.out";
1958  int i,j ;
1959  CellType Cell;
1960
1961  /* Get cod the delta = energy*/
1962  getcod(dp, lastpos);
1963
1964  printf("xcod=%.5e mm zcod=% .5e mm \n", globval.CODvect[0]*1e3, globval.CODvect[2]*1e3);
1965
1966  if ((outf = fopen(fic, "w")) == NULL)
1967  {
1968    fprintf(stdout, "Enveloppe: error while opening file %s\n", fic);
1969    exit_(1);
1970  }
1971
1972  x1[0] =  x + globval.CODvect[0]; x1[1] = px + globval.CODvect[1];
1973  x1[2] =  y + globval.CODvect[2]; x1[3] = py + globval.CODvect[3];
1974  x1[4] = dp; x1[5] = 0e0;
1975
1976  fprintf(outf,"# i    x   xp  z   zp   delta cT \n");
1977
1978  for (j = 1; j <= nturn; j++)
1979  {
1980    for (i = 0; i< globval.Cell_nLoc; i++)
1981    {/* loop over full ring */
1982
1983      getelem(i, &Cell);
1984      Cell_Pass(i,i+1, x1, lastpos);
1985      if (lastpos != i+1)
1986      {
1987       printf("Unstable motion ...\n"); exit_(1);
1988      }
1989
1990      fprintf(outf,"%6.2f % .5e % .5e % .5e % .5e % .5e % .5e\n",
1991              Cell.S, x1[0],x1[1],x1[2],x1[3],x1[4],x1[5]);
1992    }
1993  }
1994}
1995
1996
1997/****************************************************************************/
1998/* void Multipole_thicksext(const char *fic_hcorr, const char *fic_vcorr,
1999                            const char *fic_skew)
2000
2001   Purpose:
2002       Set multipole in dipoles, quadrupoles, thick sextupoles, skew quadrupole,
2003           horizontal and vertical corrector.
2004
2005   Input:
2006       none
2007
2008   Output:
2009       none
2010
2011   Return:
2012       none
2013
2014   Global variables:
2015       trace
2016
2017   Specific functions:
2018       getelem, SetKLpar, GetKpar
2019
2020   Comments:
2021       Test for short and long quadrupole could be changed using the length
2022       instead of the name. Maybe more portable, in particular if periodicity
2023       is broken
2024       Should be rewritten because list already exists now ..
2025
2026       Copy from Tracy II.
2027****************************************************************************/
2028
2029void Multipole_thicksext(const char *fic_hcorr, const char *fic_vcorr, const char *fic_skew)
2030{
2031  int i = 0;
2032  int ndip  = 0,  /* Number of dipoles */
2033      nquad = 0,  /* Number of quadrupoles */
2034      nsext = 0,  /* Number of sextupoles  */
2035      nhcorr= 0,  /* Number of horizontal correctors */
2036      nvcorr= 0,  /* Number of vertical correctors */
2037      nqcorr= 0;  /* Number of skew quadrupoles */
2038
2039  int dlist[500];     /* dipole list */
2040  int qlist[500];     /* Quadrupole list */
2041  int slist[500];     /* Sextupole list */
2042  int hcorrlist[120]; /* horizontal corrector list */
2043  int vcorrlist[120]; /* vertical corrector list */
2044  int qcorrlist[120]; /* skew quad list */
2045  int hcorrlistThick[120]; /* horizontal corrector list */
2046  int vcorrlistThick[120]; /* vertical corrector list */
2047  int qcorrlistThick[120]; /* skew quad list */
2048
2049  CellType Cell; 
2050
2051  int    mOrder = 0;     /* multipole order */
2052  double mKL = 0.0 ;     /* multipole integrated strength */
2053  double corr_strength = 0.0;
2054  double hcorr[120], vcorr[120], qcorr[120];
2055  double b2 = 0.0, b3 = 0.0;
2056  double dBoB2 = 0.0, dBoB3 = 0.0, dBoB4 = 0.0, dBoB5 = 0.0, dBoB6 = 0.0,
2057         dBoB7 = 0.0, dBoB9 = 0.0, dBoB11 = 0.0, dBoB15 = 0.0, dBoB21 = 0.0,
2058         dBoB27 = 0.0;
2059  double dBoB6C = 0.0, dBoB6L = 0.0, dBoB10C = 0.0, dBoB10L = 0.0,
2060         dBoB14C = 0.0, dBoB14L = 0.0, dBoB3C = 0.0, dBoB3L = 0.0,
2061         dBoB4C = 0.0, dBoB4L = 0.0;
2062  double dBoB5rms = 0.0, dBoB7rms = 0.0;
2063  double x0i = 0.0, x02i = 0.0, x03i = 0.0, x04i = 0.0, x05i = 0.0,
2064         x06i = 0.0, x07i = 0.0, x08i = 0.0, x012i = 0.0, x010i = 0.0,
2065         x018i = 0.0, x024i = 0.0, x1i = 0.0;
2066  double theta = 0.0, brho = 0.0, conv = 0.0 ;
2067
2068  FILE *fi;
2069/*********************************************************/
2070
2071
2072
2073  printf("Enter multipole ... \n");
2074
2075/* Make lists of dipoles, quadrupoles and  sextupoles */
2076  for (i = 0; i <= globval.Cell_nLoc; i++)
2077  {
2078    getelem(i, &Cell); /* get element */
2079
2080    if (Cell.Elem.Pkind == Mpole)
2081    {
2082      if (Cell.Elem.M->Pirho!= 0.0)
2083      {
2084        dlist[ndip] = i;
2085        ndip++;
2086        if (trace) printf("%s % f\n",Cell.Elem.PName, Cell.Elem.M->PB[0 + HOMmax]);
2087      }
2088      else if (Cell.Elem.M->PBpar[2L + HOMmax] != 0.0)
2089      {
2090        qlist[nquad] = i;
2091        nquad++;
2092        if (trace) printf("%s % f\n",Cell.Elem.PName, Cell.Elem.M->PBpar[2L + HOMmax]);
2093      }
2094      else if (Cell.Elem.M->PBpar[3L + HOMmax] != 0.0)
2095      {
2096        slist[nsext] = i;
2097        nsext++;
2098        if (trace) printf("%s % f\n",Cell.Elem.PName, Cell.Elem.M->PBpar[3L + HOMmax]);
2099      } 
2100      else if ( Cell.Elem.PName[0] == 'c' && Cell.Elem.PName[1] == 'h')
2101      {
2102        hcorrlist[nhcorr] = i;
2103        nhcorr++;
2104        if (trace) printf("%s \n",Cell.Elem.PName);
2105      }
2106      else if ( Cell.Elem.PName[0] == 'c' && Cell.Elem.PName[1] == 'v')
2107      {
2108        vcorrlist[nvcorr] = i;
2109        nvcorr++;
2110        if (trace) printf("%s \n",Cell.Elem.PName);
2111      }
2112      else if ( Cell.Elem.PName[0] == 'q' && Cell.Elem.PName[1] == 't')
2113      {
2114        qcorrlist[nqcorr] = i;
2115        nqcorr++;
2116        if (trace) printf("%s \n",Cell.Elem.PName);
2117      }
2118    }
2119  }
2120
2121
2122 /* find sextupole associated with the corrector */
2123 // solution 1: find by names
2124 // solution 2: use a predfined list
2125 // solution 3: smothing smart ???
2126  for (i=0; i< nhcorr; i++){
2127    if (trace) fprintf(stdout, "%d\n", i);
2128    getelem(hcorrlist[i]-1, &Cell);
2129    if (Cell.Elem.PName[0] == 's' && Cell.Elem.PName[1] == 'x')
2130      hcorrlistThick[i] = hcorrlist[i]-1;
2131    else{
2132      getelem(hcorrlist[i]+1, &Cell);
2133      if (Cell.Elem.PName[0] == 's' && Cell.Elem.PName[1] == 'x')
2134        hcorrlistThick[i] = hcorrlist[i]+1;
2135      else{
2136        getelem(hcorrlist[i]+2, &Cell);
2137        if (Cell.Elem.PName[0] == 's' && Cell.Elem.PName[1] == 'x')
2138          hcorrlistThick[i] = hcorrlist[i]+2;
2139        else{
2140          getelem(hcorrlist[i]-2, &Cell);
2141          if (Cell.Elem.PName[0] == 's' && Cell.Elem.PName[1] == 'x')
2142            hcorrlistThick[i] = hcorrlist[i]-2;
2143          else{
2144            getelem(hcorrlist[i]+3, &Cell);
2145            if (Cell.Elem.PName[0] == 's' && Cell.Elem.PName[1] == 'x')
2146              hcorrlistThick[i] = hcorrlist[i]+3;
2147            else{
2148              getelem(hcorrlist[i]-3, &Cell);
2149              if (Cell.Elem.PName[0] == 's' && Cell.Elem.PName[1] == 'x')
2150                hcorrlistThick[i] = hcorrlist[i]-3;
2151              else fprintf(stdout, "Warning Sextupole not found for VCOR\n");
2152            }
2153          }
2154        }
2155      }
2156    }
2157  }
2158
2159 for (i=0; i< nvcorr; i++){
2160   if (trace) fprintf(stdout, "%d\n", i);
2161   getelem(vcorrlist[i]-1, &Cell);
2162   if (Cell.Elem.PName[0] == 's' && Cell.Elem.PName[1] == 'x')
2163     vcorrlistThick[i] = vcorrlist[i]-1;
2164   else{
2165     getelem(vcorrlist[i]+1, &Cell);
2166     if (Cell.Elem.PName[0] == 's' && Cell.Elem.PName[1] == 'x')
2167        vcorrlistThick[i] = vcorrlist[i]+1;
2168     else{
2169       getelem(vcorrlist[i]+2, &Cell);
2170       if (Cell.Elem.PName[0] == 's' && Cell.Elem.PName[1] == 'x')
2171          vcorrlistThick[i] = vcorrlist[i]+2;
2172       else{
2173         getelem(vcorrlist[i]-2, &Cell);
2174         if (Cell.Elem.PName[0] == 's' && Cell.Elem.PName[1] == 'x')
2175             vcorrlistThick[i] = vcorrlist[i]-2;
2176         else{
2177           getelem(vcorrlist[i]+3, &Cell);
2178           if (Cell.Elem.PName[0] == 's' && Cell.Elem.PName[1] == 'x')
2179             vcorrlistThick[i] = vcorrlist[i]+3;
2180           else{
2181             getelem(vcorrlist[i]-3, &Cell);
2182             if (Cell.Elem.PName[0] == 's' && Cell.Elem.PName[1] == 'x')
2183               vcorrlistThick[i] = vcorrlist[i]-3;
2184             else fprintf(stdout, "Warning Sextupole not found for VCOR\n");
2185           }
2186         }
2187       }
2188     }
2189   }
2190 }
2191
2192 for (i=0; i< nqcorr; i++){
2193 if (trace) fprintf(stdout, "%d\n", i);
2194   getelem(qcorrlist[i]-1, &Cell);
2195   if (Cell.Elem.PName[0] == 's' && Cell.Elem.PName[1] == 'x')
2196     qcorrlistThick[i] = qcorrlist[i]-1;
2197   else{
2198     getelem(qcorrlist[i]+1, &Cell);
2199     if (Cell.Elem.PName[0] == 's' && Cell.Elem.PName[1] == 'x')
2200       qcorrlistThick[i] = qcorrlist[i]+1;
2201     else{
2202       getelem(qcorrlist[i]+2, &Cell);
2203       if (Cell.Elem.PName[0] == 's' && Cell.Elem.PName[1] == 'x')
2204         qcorrlistThick[i] = qcorrlist[i]+2;
2205       else{
2206         getelem(qcorrlist[i]-2, &Cell);
2207         if (Cell.Elem.PName[0] == 's' && Cell.Elem.PName[1] == 'x')
2208           qcorrlistThick[i] = qcorrlist[i]-2;
2209         else{
2210           getelem(qcorrlist[i]+3, &Cell);
2211           if (Cell.Elem.PName[0] == 's' && Cell.Elem.PName[1] == 'x')
2212             qcorrlistThick[i] = qcorrlist[i]+3;
2213           else{
2214             getelem(qcorrlist[i]-3, &Cell);
2215             if (Cell.Elem.PName[0] == 's' && Cell.Elem.PName[1] == 'x')
2216               qcorrlistThick[i] = qcorrlist[i]-3;
2217             else fprintf(stdout, "Warning Sextupole not found for QT\n");
2218           }
2219         }
2220       }
2221     }
2222   }
2223 }
2224
2225
2226 if (!trace) printf("Elements: ndip=%d nquad=%d  nsext=%d nhcorr=%d nvcorr=%d nqcorr=%d\n",
2227                     ndip,nquad,nsext,nhcorr,nvcorr,nqcorr);
2228
2229 /***********************************************************************************/
2230 /*                                                                                 */
2231 /*                        Set multipoles for dipole                                */
2232 /*                                                                                 */ 
2233 /*                        x0ni w/ n = p-1 for a 2p-poles                           */
2234 /*                                                                                 */ 
2235 /***********************************************************************************/
2236
2237  x0i   = 1.0/20e-3;  /* 1/radius */
2238  x02i  = x0i*x0i;
2239  x03i  = x02i*x0i;
2240  x04i  = x02i*x02i;
2241  x05i  = x04i*x0i;
2242  x06i  = x03i*x03i;
2243  x07i  = x06i*x0i;
2244
2245 // dBoB2 =  2.2e-4*1;  /* gradient, used for curve trajectory simulation */
2246  dBoB3 = -3.0e-4*1;  /* hexapole */
2247  dBoB4 =  2.0e-5*1;  /* octupole */
2248  dBoB5 = -1.0e-4*1;  /* decapole */
2249  dBoB6 = -6.0e-5*1;  /* 12-poles */
2250  dBoB7 = -1.0e-4*1;  /* 14-poles */
2251
2252 for (i = 0; i < ndip; i++)
2253 {
2254   getelem(dlist[i], &Cell);
2255   theta = Cell.Elem.PL*Cell.Elem.M->Pirho;
2256
2257   /* gradient error */
2258   mKL =GetKLpar(Cell.Fnum, Cell.Knum, mOrder=2L);
2259   mKL += dBoB2*theta*x0i;
2260   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=2L, mKL);
2261
2262   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld theta=% e mKl=% e\n",i,
2263               Cell.Elem.PName,Cell.Fnum, Cell.Knum, theta, mKL);
2264
2265   /* sextupole error */
2266   mKL = dBoB3*theta*x02i;
2267   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=3L, mKL);
2268 if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld theta=% e mKl=% e\n",i,
2269               Cell.Elem.PName,Cell.Fnum, Cell.Knum, theta, mKL);
2270
2271   /* octupole error */
2272   mKL = dBoB4*theta*x03i;
2273   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=4L, mKL);
2274 if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld theta=% e mKl=% e\n",i,
2275               Cell.Elem.PName,Cell.Fnum, Cell.Knum, theta, mKL);
2276
2277   /* decapole error */
2278   mKL = dBoB5*theta*x04i;
2279   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=5L, mKL);
2280 if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld theta=% e mKl=% e\n",i,
2281               Cell.Elem.PName,Cell.Fnum, Cell.Knum, theta, mKL);
2282
2283   /* 12-pole error */
2284   mKL = dBoB6*theta*x05i;
2285   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=6L, mKL);
2286 if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld theta=% e mKl=% e\n",i,
2287               Cell.Elem.PName,Cell.Fnum, Cell.Knum, theta, mKL);
2288
2289   /* 14-pole error */
2290   mKL = dBoB7*theta*x06i;
2291   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=7L, mKL);
2292    if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld theta=% e mKl=% e\n",i,
2293               Cell.Elem.PName,Cell.Fnum, Cell.Knum, theta, mKL);
2294
2295 }
2296
2297 /***********************************************************************************
2298  *
2299  ***********                Set multipoles for quadripole           ****************
2300  *
2301  *                          x0ni w/ n = p-2 for a 2p-poles
2302  *
2303  ***********************************************************************************/
2304
2305 x0i  = 1.0/30e-3;       /* 1/Radius in meters */
2306 b2   = 0.0;             /* Quadrupole strength */
2307 x02i = x0i*x0i;
2308 x04i = x02i*x02i;       /* 10-poles */
2309 x08i = x04i*x04i;       /* 20-poles */
2310 x012i= x08i*x04i;       /* 28-poles */
2311
2312 dBoB6C  =  2.4e-4*1;
2313 dBoB10C =  0.7e-4*1;
2314 dBoB14C =  0.9e-4*1;
2315 dBoB6L  =  0.7e-4*1;
2316 dBoB10L =  1.9e-4*1;
2317 dBoB14L =  1.0e-4*1;
2318
2319
2320 x1i  = 1.0/30e-3;       /* rayon reference = 30 mm pour mesure sextupole et octupole*/
2321 dBoB3L  =  2.9e-4*1;  /* sextupole qpole long */
2322 dBoB4L  =  -8.6e-4*1;  /* octupole qpole long */
2323 dBoB3C  =  -1.6e-4*1;  /* sextupole qpole court */
2324 dBoB4C  =  -3.4e-4*1;  /* octupole qpole court */
2325
2326
2327 for (i = 0; i < nquad; i++)
2328 {
2329   getelem(qlist[i], &Cell);
2330//    b2 = Cell.Elem.PL*GetKpar(Cell.Fnum, Cell.Knum, 2L);
2331   b2 = GetKLpar(Cell.Fnum, Cell.Knum, 2L);
2332
2333   /* 12-pole multipole error */
2334   if ((strncmp(Cell.Elem.PName,"qp2",3)==0) || (strncmp(Cell.Elem.PName,"qp7",3)==0))
2335         mKL= b2*dBoB6L*x04i;
2336   else
2337      mKL= b2*dBoB6C*x04i;
2338   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=6L, mKL);
2339   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld b2=% e mKl=% e\n",i,
2340               Cell.Elem.PName,Cell.Fnum, Cell.Knum, b2, mKL);
2341   
2342   /* 20-pole multipole error */
2343   if ((strncmp(Cell.Elem.PName,"qp2",3)==0) || (strncmp(Cell.Elem.PName,"qp7",3)==0))
2344     mKL= b2*dBoB10L*x08i;
2345   else
2346     mKL= b2*dBoB10C*x08i;
2347   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=10L, mKL);
2348   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld b2=% e mKl=% e\n",i,
2349               Cell.Elem.PName,Cell.Fnum, Cell.Knum, b2, mKL);
2350
2351   /* 28-pole multipole error */
2352   if ((strncmp(Cell.Elem.PName,"qp2",3)==0) || (strncmp(Cell.Elem.PName,"qp7",3)==0))
2353     mKL= b2*dBoB14L*x012i;
2354   else
2355     mKL= b2*dBoB14C*x012i;
2356   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=14L, mKL);
2357   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld b2=% e mKl=% e\n",i,
2358               Cell.Elem.PName,Cell.Fnum, Cell.Knum, b2, mKL);
2359
2360   /* sextupole mesure quadrupoles longs*/
2361   if ((strncmp(Cell.Elem.PName,"qp2",3)==0) || (strncmp(Cell.Elem.PName,"qp7",3)==0))
2362      mKL= b2*dBoB3L*x1i;
2363   else
2364      mKL= b2*dBoB3C*x1i;
2365   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=3L, mKL);
2366   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld b2=% e mKl=% e\n",i,
2367               Cell.Elem.PName,Cell.Fnum, Cell.Knum, b2, mKL);
2368
2369   /* octupole mesure quadrupoles longs*/
2370   if ((strncmp(Cell.Elem.PName,"qp2",3)==0) || (strncmp(Cell.Elem.PName,"qp7",3)==0))
2371      mKL= b2*dBoB4L*x1i*x1i;
2372   else
2373      mKL= b2*dBoB4C*x1i*x1i;
2374   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=4L, mKL);
2375   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld b2=% e mKl=% e\n",i,
2376               Cell.Elem.PName,Cell.Fnum, Cell.Knum, b2, mKL);
2377 }
2378
2379 /***********************************************************************************
2380  *
2381  ***********              Set multipoles for sextupole              ****************
2382  *
2383  *                        x0ni w/ n = p-3 for a 2p-poles
2384  *
2385  ***********************************************************************************/
2386
2387  b3    = 0.0;
2388  x0i   = 1.0/32e-3;
2389  x02i  = x0i*x0i;
2390  x04i  = x02i*x02i;
2391  x06i  = x04i*x02i;   /* 18-poles */
2392  x012i = x06i*x06i;   /* 30-poles */
2393  x018i = x012i*x06i;  /* 42-poles */
2394  x024i = x012i*x012i; /* 54-poles */
2395
2396  /* multipoles from dipolar unallowed component */
2397  dBoB5  =   5.4e-4*1;
2398  dBoB7  =   3.3e-4*1;
2399  dBoB5rms  =  4.7e-4*1; // for test
2400  dBoB7rms  =  2.1e-4*1; // for test
2401
2402  /* allowed multipoles */
2403  dBoB9  =  -4.7e-4*1;
2404  dBoB15 =  -9.0e-4*1;
2405  dBoB21 =  -20.9e-4*1;
2406  dBoB27 =    0.8e-4*1;
2407/*
2408  dBoB9  =  3.1e-3*1;
2409  dBoB15 =  5.0e-4*1;
2410  dBoB21 =  -2.0e-2*1;
2411  dBoB27 =  1.1e-2*1;
2412*/
2413 for (i = 0; i < nsext; i++)
2414 {
2415   getelem(slist[i], &Cell);
2416   b3 = GetKLpar(Cell.Fnum, Cell.Knum, 3L);
2417
2418   /* 10-pole multipole error */
2419   mKL= b3*dBoB5*x02i;
2420   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=5L, mKL);
2421   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld b3=% e mKl=% e\n",i,
2422               Cell.Elem.PName,Cell.Fnum, Cell.Knum, b3, mKL);
2423
2424   /* 14-pole multipole error */
2425   mKL= b3*dBoB7*x04i;
2426   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=7L, mKL);
2427   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld b3=% e mKl=% e\n",i,
2428               Cell.Elem.PName,Cell.Fnum, Cell.Knum, b3, mKL);
2429
2430   /* 18-pole multipole error */
2431   mKL= b3*dBoB9*x06i;
2432   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=9L, mKL);
2433   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld b3=% e mKl=% e\n",i,
2434               Cell.Elem.PName,Cell.Fnum, Cell.Knum, b3, mKL);
2435
2436   /* 30-pole multipole error */
2437   mKL= b3*dBoB15*x012i;
2438   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=15L, mKL);
2439   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld b3=% e mKl=% e\n",i,
2440               Cell.Elem.PName,Cell.Fnum, Cell.Knum, b3, mKL);
2441
2442   /* 42-pole multipole error */
2443   mKL= b3*dBoB21*x018i;
2444   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=21L, mKL);
2445   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld b3=% e mKl=% e\n",i,
2446               Cell.Elem.PName,Cell.Fnum, Cell.Knum, b3, mKL);
2447
2448   /* 54-pole multipole error */
2449   mKL= b3*dBoB27*x024i;
2450   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=27L, mKL);
2451   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld b3=% e mKl=% e\n",i,
2452               Cell.Elem.PName,Cell.Fnum, Cell.Knum, b3, mKL);
2453}
2454
2455 /***********************************************************************************
2456  *
2457  ******  Set multipoles for sextupole horizontal correctors         ****************
2458  *
2459  *                x0ni w/ n = p-1 for a 2p-poles
2460  *
2461  ***********************************************************************************/
2462  x0i   = 1.0/35e-3;  /* 1/radius */
2463  x02i  = x0i*x0i;
2464  x03i  = x02i*x0i;
2465  x04i  = x02i*x02i;
2466  x05i  = x04i*x0i;
2467  x06i  = x03i*x03i;
2468  x010i = x05i*x05i;
2469
2470  dBoB5  = 0.430*1;  /* decapole */
2471  dBoB7  = 0.063*1;  /* 14-poles */
2472  dBoB11 =-0.037*1;  /* 22-poles */
2473
2474  brho = globval.Energy/0.299792458; /* magnetic rigidity */
2475  conv = 8.14e-4;  /*conversion des A en T.m*/
2476
2477  /* open H corrector file */
2478  if ((fi = fopen(fic_hcorr,"r")) == NULL)
2479  {
2480    fprintf(stderr, "Error while opening file %s \n",fic_hcorr);
2481    exit(1);
2482  }
2483
2484  for (i = 0; i < nhcorr; i++)
2485  {
2486    fscanf(fi,"%le \n", &hcorr[i]);
2487  }
2488  fclose(fi); /* close H corrector file */
2489
2490  for (i = 0; i < nhcorr; i++){
2491    getelem(hcorrlistThick[i], &Cell);
2492    corr_strength = hcorr[i]*conv/brho;
2493
2494    /* gradient error */
2495    mKL = GetKLpar(Cell.Fnum, Cell.Knum, mOrder=5L);
2496    mKL += dBoB5*corr_strength*x04i;
2497    SetKLpar(Cell.Fnum, Cell.Knum, mOrder=5L, mKL);
2498
2499    if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld BL/brho=% e mKl=% e\n",i,
2500    Cell.Elem.PName,Cell.Fnum, Cell.Knum, corr_strength, mKL);
2501    /* 14-pole error */
2502    mKL = GetKLpar(Cell.Fnum, Cell.Knum, mOrder=7L);
2503    mKL += dBoB7*corr_strength*x06i;
2504    SetKLpar(Cell.Fnum, Cell.Knum, mOrder=7L, mKL);
2505
2506    if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld BL/brho=% e mKl=% e\n",i,
2507    Cell.Elem.PName,Cell.Fnum, Cell.Knum, corr_strength, mKL);
2508
2509    /* 22-pole error */
2510    mKL = GetKLpar(Cell.Fnum, Cell.Knum, mOrder=11L);
2511    mKL += dBoB11*corr_strength*x010i;
2512    SetKLpar(Cell.Fnum, Cell.Knum, mOrder=11, mKL);
2513
2514    if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld BL/brho=% e mKl=% e\n",i,
2515    Cell.Elem.PName,Cell.Fnum, Cell.Knum, corr_strength, mKL);
2516  }
2517
2518 /***********************************************************************************
2519  *
2520  ******  Set multipoles for vertical correctors           ****************
2521  *
2522  *                    x0ni w/ n = p-1 for a 2p-poles
2523  *
2524  ***********************************************************************************/
2525
2526  x0i   = 1.0/35e-3;  /* 1/radius */
2527  x02i  = x0i*x0i;
2528  x03i  = x02i*x0i;
2529  x04i  = x02i*x02i;
2530  x05i  = x04i*x0i;
2531  x06i  = x03i*x03i;
2532  x010i = x05i*x05i;
2533
2534  dBoB5  = -0.430*1;  /* decapole */
2535  dBoB7  =  0.063*1;  /* 14-poles */
2536  dBoB11 =  0.037*1;  /* 22-poles */
2537
2538  brho = globval.Energy/0.299792458; /* magnetic rigidity */
2539  conv = 4.642e-4;  /*conversion des A en T.m*/
2540
2541
2542  /* open V corrector file */
2543  if ((fi = fopen(fic_vcorr,"r")) == NULL)
2544  {
2545    fprintf(stderr, "Error while opening file %s \n",fic_vcorr);
2546    exit(1);
2547  }
2548
2549  for (i = 0; i < nvcorr; i++){
2550    fscanf(fi,"%le\n", &vcorr[i]);
2551  }
2552  fclose(fi); /* close V corrector file */
2553
2554//  for (i = 0; i < nvcorr; i++)
2555//  {
2556//    getelem(vcorrlist[i], &Cell);
2557//    corr_strength = vcorr[i]*conv/brho;
2558//
2559//    /* skew decapole error */
2560//    mKL = dBoB5*corr_strength*x04i;
2561//    SetKLpar(Cell.Fnum, Cell.Knum, mOrder=-5L, mKL);
2562//
2563//    if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld BL/brho=% e mKl=% e\n",i,
2564//                Cell.Elem.PName,Cell.Fnum, Cell.Knum, corr_strength, mKL);
2565//    /* skew 14-pole error */
2566//    mKL = dBoB7*corr_strength*x06i;
2567//    SetKLpar(Cell.Fnum, Cell.Knum, mOrder=-7L, mKL);
2568//
2569//    if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld BL/brho=% e mKl=% e\n",i,
2570//             Cell.Elem.PName,Cell.Fnum, Cell.Knum, corr_strength, mKL);
2571//
2572//    /* skew 22-pole error */
2573//    mKL = dBoB11*corr_strength*x010i;
2574//    SetKLpar(Cell.Fnum, Cell.Knum, mOrder=-11L, mKL);
2575//
2576//    if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld BL/brho=% e mKl=% e\n",i,
2577//                Cell.Elem.PName,Cell.Fnum, Cell.Knum, corr_strength, mKL);
2578//  }
2579
2580 for (i = 0; i < nvcorr; i++)
2581 {
2582   getelem(vcorrlistThick[i], &Cell);
2583   corr_strength = vcorr[i]*conv/brho;
2584
2585   /* skew decapole error */
2586   mKL = GetKLpar(Cell.Fnum, Cell.Knum, mOrder=-5L);
2587   mKL += dBoB5*corr_strength*x04i;
2588   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=-5L, mKL);
2589
2590   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld BL/brho=% e mKl=% e\n",i,
2591   Cell.Elem.PName,Cell.Fnum, Cell.Knum, corr_strength, mKL);
2592
2593   /* skew 14-pole error */
2594   mKL = GetKLpar(Cell.Fnum, Cell.Knum, mOrder=-7L);
2595   mKL += dBoB7*corr_strength*x06i;
2596   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=-7L, mKL);
2597
2598   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld BL/brho=% e mKl=% e\n",i,
2599   Cell.Elem.PName,Cell.Fnum, Cell.Knum, corr_strength, mKL);
2600
2601   /* skew 22-pole error */
2602   mKL = GetKLpar(Cell.Fnum, Cell.Knum, mOrder=-11L);
2603   mKL += dBoB11*corr_strength*x010i;
2604   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=-11L, mKL);
2605
2606   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld BL/brho=% e mKl=% e\n",i,
2607   Cell.Elem.PName,Cell.Fnum, Cell.Knum, corr_strength, mKL);
2608 }
2609 /***********************************************************************************
2610  *
2611  ******                Set multipoles for skew quadripole           ****************
2612  *
2613  *                        x0ni w/ n = p-2 for a 2p-poles
2614  *
2615  ***********************************************************************************/
2616
2617 /* Set multipoles for skew quad */
2618  x0i   = 1.0/35e-3;  /* 1/radius */
2619  x02i  = x0i*x0i;
2620
2621  dBoB4  = -0.680*1;  /* Octupole */
2622
2623  /* open skew quaI (A) *
2624310
2625450
2626500
2627520
2628540
2629550
2630560
2631d file */
2632
2633  // brho = 2.75/0.299792458; /* magnetic rigidity */
2634   brho = globval.Energy/0.299792458; /* magnetic rigidity */
2635   conv = 93.83e-4;  /*conversion des A en T*/
2636
2637
2638  if ((fi = fopen(fic_skew,"r")) == NULL)
2639  {
2640    fprintf(stderr, "Error while opening file %s \n",fic_skew);
2641    exit(1);
2642  }
2643
2644  for (i = 0; i < nqcorr; i++)
2645  {
2646    fscanf(fi,"%le \n", &qcorr[i]);
2647  }
2648  fclose(fi); /* close skew quad file */
2649
2650//  for (i = 0; i < nqcorr; i++)
2651//  {
2652//    getelem(qcorrlist[i], &Cell);
2653//
2654//    /* skew octupole */
2655//    mKL = dBoB4*qcorr[i]*conv/brho*x02i;
2656//    SetKLpar(Cell.Fnum, Cell.Knum, mOrder=-4L, mKL);
2657//
2658//    if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld BL/brho=% e mKl=% e\n",i,
2659//                Cell.Elem.PName,Cell.Fnum, Cell.Knum, corr_strength, mKL);
2660//  }
2661 for (i = 0; i < nqcorr; i++)
2662 {
2663   getelem(qcorrlist[i], &Cell);
2664
2665   /* skew octupole */
2666   mKL = GetKLpar(Cell.Fnum, Cell.Knum, mOrder=-4L);
2667   mKL += dBoB4*qcorr[i]*conv/brho*x02i;
2668   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=-4L, mKL);
2669
2670   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld BL/brho=% e mKl=% e\n",i,
2671   Cell.Elem.PName,Cell.Fnum, Cell.Knum, corr_strength, mKL);
2672 }
2673}
2674
2675/****************************************************************************/
2676/* void Multipole_thinsext(const char *fic_hcorr, const char *fic_vcorr,
2677                           const char *fic_skew)
2678
2679   Purpose:
2680       Set multipole in dipoles, quadrupoles, thin sextupoles, skew quadrupole,
2681           horizontal and vertical corrector.
2682
2683   Input:
2684       none
2685
2686   Output:
2687       none
2688
2689   Return:
2690       none
2691
2692   Global variables:
2693       trace
2694
2695   Specific functions:
2696       getelem, SetKLpar, GetKpar
2697
2698   Comments:
2699       Test for short and long quadrupole could be changed using the length
2700       instead of the name. Maybe more portable, in particular if periodicity
2701       is broken
2702       Should be rewritten because list already exists now ..
2703
2704****************************************************************************/
2705
2706void Multipole_thinsext(const char *fic_hcorr, const char *fic_vcorr, const char *fic_skew)
2707{
2708  int i = 0;
2709  int ndip  = 0,  /* Number of dipoles */
2710      nquad = 0,  /* Number of quadrupoles */
2711      nsext = 0,  /* Number of sextupoles  */
2712      nhcorr= 0,  /* Number of horizontal correctors */
2713      nvcorr= 0,  /* Number of vertical correctors */
2714      nqcorr= 0;  /* Number of skew quadrupoles */
2715
2716  int dlist[500];     /* dipole list */
2717  int qlist[500];     /* Quadrupole list */
2718  int slist[500];     /* Sextupole list */
2719  int hcorrlist[120]; /* horizontal corrector list */
2720  int vcorrlist[120]; /* vertical corrector list */
2721  int qcorrlist[120]; /* skew quad list */
2722
2723  CellType Cell;
2724
2725  int    mOrder = 0;     /* multipole order */
2726  double mKL = 0.0 ;     /* multipole integrated strength */
2727  double corr_strength = 0.0;
2728  double hcorr[120], vcorr[120], qcorr[120];
2729  double b2 = 0.0, b3 = 0.0;
2730  double dBoB2 = 0.0, dBoB3 = 0.0, dBoB4 = 0.0, dBoB5 = 0.0, dBoB6 = 0.0,
2731         dBoB7 = 0.0, dBoB9 = 0.0, dBoB11 = 0.0, dBoB15 = 0.0, dBoB21 = 0.0,
2732         dBoB27;
2733  double  dBoB6C = 0.0,  dBoB6L = 0.0, dBoB10C = 0.0, dBoB10L = 0.0,
2734         dBoB14C = 0.0, dBoB14L = 0.0,  dBoB3C = 0.0,  dBoB3L = 0.0,
2735          dBoB4C = 0.0,  dBoB4L = 0.0;
2736  double x0i = 0.0, x02i = 0.0, x03i = 0.0, x04i = 0.0, x05i = 0.0,
2737         x06i = 0.0, x07i = 0.0, x08i = 0.0, x012i = 0.0, x010i = 0.0,
2738         x018i = 0.0, x024i = 0.0, x1i = 0.0;
2739  double theta = 0.0, brho = 0.0, conv = 0.0 ;
2740 
2741
2742  FILE *fi;
2743/*********************************************************/
2744
2745  printf("Enter multipole ... \n");
2746
2747/* Make lists of dipoles, quadrupoles and  sextupoles */
2748  for (i = 0; i <= globval.Cell_nLoc; i++)
2749  {
2750    getelem(i, &Cell); /* get element */
2751
2752    if (Cell.Elem.Pkind == Mpole)
2753    {
2754      if (fabs(Cell.Elem.M->Pirho) > 0.0)
2755      {
2756        dlist[ndip] = i;
2757        ndip++;
2758        if (trace) printf("%s % f\n",Cell.Elem.PName, Cell.Elem.M->PB[0 + HOMmax]);
2759      }
2760      else if (fabs(Cell.Elem.M->PBpar[2L + HOMmax]) > 0.0)
2761      {
2762        qlist[nquad] = i;
2763        nquad++;
2764        if (trace) printf("%s % f\n",Cell.Elem.PName, Cell.Elem.M->PBpar[2L + HOMmax]);
2765      }
2766      else if (fabs(Cell.Elem.M->PBpar[3L + HOMmax]) > 0.0)
2767      {
2768        slist[nsext] = i;
2769        nsext++;
2770        if (trace) printf("%s % f\n",Cell.Elem.PName, Cell.Elem.M->PBpar[3L + HOMmax]);
2771      }
2772      else if ( Cell.Elem.PName[0] == 'c' && Cell.Elem.PName[1] == 'h')
2773      {
2774        hcorrlist[nhcorr] = i;
2775        nhcorr++;
2776        if (trace) printf("%s \n",Cell.Elem.PName);
2777      }
2778      else if ( Cell.Elem.PName[0] == 'c' && Cell.Elem.PName[1] == 'v')
2779      {
2780        vcorrlist[nvcorr] = i;
2781        nvcorr++;
2782        if (trace) printf("%s \n",Cell.Elem.PName);
2783      }
2784      else if ( Cell.Elem.PName[0] == 'q' && Cell.Elem.PName[1] == 't')
2785      {
2786        qcorrlist[nqcorr] = i;
2787        nqcorr++;
2788        if (trace) printf("%s \n",Cell.Elem.PName);
2789      }
2790    }
2791  }
2792
2793 if (!trace) printf("Elements: ndip=%d nquad=%d  nsext=%d nhcorr=%d nvcorr=%d nqcorr=%d\n",
2794                     ndip,nquad,nsext,nhcorr,nvcorr,nqcorr);
2795
2796 /***********************************************************************************/
2797 /*                                                                                 */
2798 /***********                Set multipoles for dipole               ****************/
2799 /*
2800  *                        x0ni w/ n = p-1 for a 2p-poles
2801  */
2802 /***********************************************************************************/
2803 
2804  x0i   = 1.0/20e-3;  /* 1/radius */
2805  x02i  = x0i*x0i;
2806  x03i  = x02i*x0i;
2807  x04i  = x02i*x02i;
2808  x05i  = x04i*x0i;
2809  x06i  = x03i*x03i;
2810  x07i  = x06i*x0i;
2811
2812  dBoB2 =  1.7e-4*0;  /* gradient */
2813  dBoB3 = -3.7e-4*0;  /* hexapole */
2814  dBoB4 = -4.1e-5*0;  /* octupole */
2815  dBoB5 = -9.6e-5*0;  /* decapole */
2816  dBoB6 = -5.7e-5*0;  /* 12-poles */
2817  dBoB7 = -4.3e-5*0;  /* 14-poles */
2818
2819 for (i = 0; i < ndip; i++)
2820 {
2821   getelem(dlist[i], &Cell);
2822   theta = Cell.Elem.PL*Cell.Elem.M->Pirho;
2823
2824   /* gradient error */
2825   mKL = dBoB2*theta*x0i;
2826   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=2L, mKL);
2827
2828   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld theta=% e mKl=% e\n",i,
2829               Cell.Elem.PName,Cell.Fnum, Cell.Knum, theta, mKL);
2830
2831   /* sextupole error */
2832   mKL = dBoB3*theta*x02i;
2833   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=3L, mKL);
2834
2835   /* octupole error */
2836   mKL = dBoB4*theta*x03i;
2837   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=4L, mKL);
2838
2839   /* decapole error */
2840   mKL = dBoB5*theta*x04i;
2841   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=5L, mKL);
2842
2843   /* 12-pole error */
2844   mKL = dBoB6*theta*x05i;
2845   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=6L, mKL);
2846
2847   /* 14-pole error */
2848   mKL = dBoB7*theta*x06i;
2849   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=7L, mKL);
2850 }
2851
2852 /***********************************************************************************/
2853 /*                                                                                 */
2854 /***********                Set multipoles for quadripole           ****************/
2855 /*
2856  *                          x0ni w/ n = p-2 for a 2p-poles
2857  */
2858 /***********************************************************************************/
2859
2860 x0i  = 1.0/30e-3;       /* 1/Radius in meters */
2861 b2   = 0.0;             /* Quadrupole strength */
2862 x02i = x0i*x0i;
2863 x04i = x02i*x02i;       /* 10-poles */
2864 x08i = x04i*x04i;       /* 20-poles */
2865 x012i= x08i*x04i;       /* 28-poles */
2866
2867 dBoB6C  =  2.4e-4*1;
2868 dBoB10C =  0.7e-4*1;
2869 dBoB14C =  0.9e-4*1;
2870 dBoB6L  =  0.7e-4*1;
2871 dBoB10L =  1.9e-4*1;
2872 dBoB14L =  1.0e-4*1;
2873
2874
2875 x1i  = 1.0/30e-3;      /* rayon reference = 30 mm pour mesure sextupole et octupole*/
2876 dBoB3L  =   2.9e-4*1;   /* sextupole qpole long */
2877 dBoB4L  =  -8.6e-4*1;  /* octupole qpole long */
2878 dBoB3C  =  -1.6e-4*1;  /* sextupole qpole court */
2879 dBoB4C  =  -3.4e-4*1;  /* octupole qpole court */
2880
2881
2882 for (i = 0; i < nquad; i++)
2883 {
2884   getelem(qlist[i], &Cell);
2885   b2 = Cell.Elem.PL*GetKpar(Cell.Fnum, Cell.Knum, 2L);
2886
2887   /* 12-pole multipole error */
2888   if ((strncmp(Cell.Elem.PName,"qp2",3)==0) || (strncmp(Cell.Elem.PName,"qp7",3)==0))
2889      mKL= b2*dBoB6L*x04i;
2890   else
2891      mKL= b2*dBoB6C*x04i;
2892   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=6L, mKL);
2893   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld b2=% e mKl=% e\n",i,
2894               Cell.Elem.PName,Cell.Fnum, Cell.Knum, b2, mKL);
2895
2896   /* 20-pole multipole error */
2897   if ((strncmp(Cell.Elem.PName,"qp2",3)==0) || (strncmp(Cell.Elem.PName,"qp7",3)==0))
2898     mKL= b2*dBoB10L*x08i;
2899   else
2900     mKL= b2*dBoB10C*x08i;
2901   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=10L, mKL);
2902   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld b2=% e mKl=% e\n",i,
2903               Cell.Elem.PName,Cell.Fnum, Cell.Knum, b2, mKL);
2904
2905   /* 28-pole multipole error */
2906   if ((strncmp(Cell.Elem.PName,"qp2",3)==0) || (strncmp(Cell.Elem.PName,"qp7",3)==0))
2907     mKL= b2*dBoB14L*x012i;
2908   else
2909     mKL= b2*dBoB14C*x012i;
2910   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=14L, mKL);
2911   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld b2=% e mKl=% e\n",i,
2912               Cell.Elem.PName,Cell.Fnum, Cell.Knum, b2, mKL);
2913
2914/* sextupole mesure quadrupoles longs*/
2915   if ((strncmp(Cell.Elem.PName,"qp2",3)==0) || (strncmp(Cell.Elem.PName,"qp7",3)==0))
2916      mKL= b2*dBoB3L*x1i;
2917   else
2918      mKL= b2*dBoB3C*x1i;
2919   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=3L, mKL);
2920   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld b2=% e mKl=% e\n",i,
2921               Cell.Elem.PName,Cell.Fnum, Cell.Knum, b2, mKL);
2922
2923   /* octupole mesure quadrupoles longs*/
2924   if ((strncmp(Cell.Elem.PName,"qp2",3)==0) || (strncmp(Cell.Elem.PName,"qp7",3)==0))
2925      mKL= b2*dBoB4L*x1i*x1i;
2926   else
2927      mKL= b2*dBoB4C*x1i*x1i;
2928   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=4L, mKL);
2929   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld b2=% e mKl=% e\n",i,
2930               Cell.Elem.PName,Cell.Fnum, Cell.Knum, b2, mKL);
2931
2932 }
2933
2934 /***********************************************************************************/
2935 /*                                                                                 */
2936 /***********              Set multipoles for sextupole              ****************/
2937 /*
2938  *                        x0ni w/ n = p-3 for a 2p-poles
2939  */
2940 /***********************************************************************************/
2941 
2942  b3    = 0.0;
2943  x0i   = 1.0/32e-3;
2944  x02i  = x0i*x0i;
2945  x04i  = x02i*x02i;
2946  x06i  = x04i*x02i;   /* 18-poles */
2947  x012i = x06i*x06i;   /* 30-poles */
2948  x018i = x012i*x06i;  /* 42-poles */
2949  x024i = x012i*x012i; /* 54-poles */
2950   
2951  dBoB9  =  -4.7e-4*1;
2952  dBoB15 =  -9.0e-4*1;
2953  dBoB21 =  -20.9e-4*1;
2954  dBoB27 =  0.8e-4*1 ;
2955/*
2956  dBoB9  =  3.1e-3*1;
2957  dBoB15 =  5.0e-4*1;
2958  dBoB21 =  -2.0e-2*1;
2959  dBoB27 =  1.1e-2*1;
2960*/
2961
2962 for (i = 0; i < nsext; i++)
2963 {
2964   getelem(slist[i], &Cell);
2965   b3 = GetKpar(Cell.Fnum, Cell.Knum, 3L);
2966
2967   /* 18-pole multipole error */
2968   mKL= b3*dBoB9*x06i;
2969   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=9L, mKL);
2970   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld b3=% e mKl=% e\n",i,
2971               Cell.Elem.PName,Cell.Fnum, Cell.Knum, b3, mKL);
2972
2973   /* 30-pole multipole error */
2974   mKL= b3*dBoB15*x012i;
2975   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=15L, mKL);
2976   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld b3=% e mKl=% e\n",i,
2977               Cell.Elem.PName,Cell.Fnum, Cell.Knum, b3, mKL);
2978
2979   /* 42-pole multipole error */
2980   mKL= b3*dBoB21*x018i;
2981   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=21L, mKL);
2982   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld b3=% e mKl=% e\n",i,
2983               Cell.Elem.PName,Cell.Fnum, Cell.Knum, b3, mKL);
2984
2985   /* 54-pole multipole error */
2986   mKL= b3*dBoB27*x024i;
2987   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=27L, mKL);
2988   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld b3=% e mKl=% e\n",i,
2989               Cell.Elem.PName,Cell.Fnum, Cell.Knum, b3, mKL);
2990}
2991
2992 /***********************************************************************************/
2993 /*                                                                                 */
2994 /******            Set multipoles for horizontal correctors         ****************/
2995 /*
2996  *                x0ni w/ n = p-1 for a 2p-poles
2997  */
2998 /***********************************************************************************/
2999  x0i   = 1.0/35e-3;  /* 1/radius */
3000  x02i  = x0i*x0i;
3001  x03i  = x02i*x0i;
3002  x04i  = x02i*x02i;
3003  x05i  = x04i*x0i;
3004  x06i  = x03i*x03i;
3005  x010i = x05i*x05i;
3006
3007  dBoB5  = 0.430*1;  /* decapole */
3008  dBoB7  = 0.063*1;  /* 14-poles */
3009  dBoB11 =-0.037*1;  /* 22-poles */
3010
3011  brho = 2.75/0.299792458; /* magnetic rigidity */
3012  conv = 8.14e-4;  /*conversion des A en T.m*/
3013
3014  /* open H corrector file */
3015  if ((fi = fopen(fic_hcorr,"r")) == NULL)
3016  {
3017    fprintf(stdout, "Error while opening file %s \n",fic_hcorr);
3018    exit_(1);
3019  }
3020
3021  for (i = 0; i < nhcorr; i++)
3022  {
3023    fscanf(fi,"%le \n", &hcorr[i]);
3024  }
3025  fclose(fi); /* close H corrector file */
3026
3027 for (i = 0; i < nhcorr; i++)
3028 {
3029   getelem(hcorrlist[i], &Cell);
3030   corr_strength = hcorr[i]*conv/brho;
3031
3032   /* gradient error */
3033   mKL = dBoB5*corr_strength*x04i;
3034   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=5L, mKL);
3035
3036   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld BL/brho=% e mKl=% e\n",i,
3037               Cell.Elem.PName,Cell.Fnum, Cell.Knum, corr_strength, mKL);
3038   /* 14-pole error */
3039   mKL = dBoB7*corr_strength*x06i;
3040   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=7L, mKL);
3041
3042   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld BL/brho=% e mKl=% e\n",i,
3043            Cell.Elem.PName,Cell.Fnum, Cell.Knum, corr_strength, mKL);
3044
3045   /* 22-pole error */
3046   mKL = dBoB11*corr_strength*x010i;
3047   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=11, mKL);
3048
3049   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld BL/brho=% e mKl=% e\n",i,
3050               Cell.Elem.PName,Cell.Fnum, Cell.Knum, corr_strength, mKL);
3051 }
3052
3053 /***********************************************************************************/
3054 /*                                                                                 */
3055 /******            Set multipoles for vertical correctors           ****************/
3056 /*
3057  *                    x0ni w/ n = p-1 for a 2p-poles
3058  */
3059 /***********************************************************************************/
3060
3061  x0i   = 1.0/35e-3;  /* 1/radius */
3062  x02i  = x0i*x0i;
3063  x03i  = x02i*x0i;
3064  x04i  = x02i*x02i;
3065  x05i  = x04i*x0i;
3066  x06i  = x03i*x03i;
3067  x010i = x05i*x05i;
3068
3069  dBoB5  = -0.430*1;  /* decapole */
3070  dBoB7  =  0.063*1;  /* 14-poles */
3071  dBoB11 =  0.037*1;  /* 22-poles */
3072
3073  brho = 2.75/0.299792458; /* magnetic rigidity */
3074  conv = 4.642e-4;  /*conversion des A en T.m*/
3075
3076  /* open V corrector file */
3077  if ((fi = fopen(fic_vcorr,"r")) == NULL)
3078  {
3079    fprintf(stdout, "Error while opening file %s \n",fic_vcorr);
3080    exit_(1);
3081  }
3082
3083  for (i = 0; i < nvcorr; i++)
3084  {
3085    //   fscanf(fi,"%s %le %le %le \n", dummy,&dummyf,&dummyf,&vcorr[i]);
3086    fscanf(fi,"%le\n", &vcorr[i]); 
3087}
3088  fclose(fi); /* close V corrector file */
3089
3090 for (i = 0; i < nvcorr; i++)
3091 {
3092   getelem(vcorrlist[i], &Cell);
3093   corr_strength = vcorr[i]*conv/brho;
3094
3095   /* skew decapole error */
3096   mKL = dBoB5*corr_strength*x04i;
3097   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=-5L, mKL);
3098
3099   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld BL/brho=% e mKl=% e\n",i,
3100               Cell.Elem.PName,Cell.Fnum, Cell.Knum, corr_strength, mKL);
3101   /* skew 14-pole error */
3102   mKL = dBoB7*corr_strength*x06i;
3103   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=-7L, mKL);
3104
3105   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld BL/brho=% e mKl=% e\n",i,
3106            Cell.Elem.PName,Cell.Fnum, Cell.Knum, corr_strength, mKL);
3107
3108   /* skew 22-pole error */
3109   mKL = dBoB11*corr_strength*x010i;
3110   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=-11, mKL);
3111
3112   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld BL/brho=% e mKl=% e\n",i,
3113               Cell.Elem.PName,Cell.Fnum, Cell.Knum, corr_strength, mKL);
3114 }
3115
3116 /***********************************************************************************/
3117 /*                                                                                 */
3118 /******                Set multipoles for skew quadripole           ****************/
3119 /*
3120  *                        x0ni w/ n = p-2 for a 2p-poles
3121  */
3122 /***********************************************************************************/
3123
3124 /* Set multipoles for skew quad */
3125  x0i   = 1.0/35e-3;  /* 1/radius */
3126  x02i  = x0i*x0i;
3127
3128  dBoB4  = -0.680*1;  /* Octupole */
3129
3130  /* open skew quaI (A) *
3131310
3132450
3133500
3134520
3135540
3136550
3137560
3138d file */
3139
3140  brho = 2.75/0.299792458; /* magnetic rigidity */
3141  conv = 93.83e-4;  /*conversion des A en T*/
3142
3143
3144  /* open skew quad file */
3145  if ((fi = fopen(fic_skew,"r")) == NULL)
3146  {
3147    fprintf(stdout, "Error while opening file %s \n",fic_skew);
3148    exit_(1);
3149  }
3150
3151  for (i = 0; i < nqcorr; i++)
3152  {
3153    fscanf(fi,"%le \n", &qcorr[i]);
3154  }
3155  fclose(fi); /* close skew quad file */
3156
3157 for (i = 0; i < nqcorr; i++)
3158 {
3159   getelem(qcorrlist[i], &Cell);
3160
3161   /* skew octupole */
3162   mKL = dBoB4*qcorr[i]*conv/brho*x02i;
3163   SetKLpar(Cell.Fnum, Cell.Knum, mOrder=-4L, mKL);
3164
3165   if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld BL/brho=% e mKl=% e\n",i,
3166               Cell.Elem.PName,Cell.Fnum, Cell.Knum, corr_strength, mKL);
3167 }
3168}
3169
3170/****************************************************************************/
3171/* void SetSkewQuad(void)
3172
3173   Purpose:
3174       Set SkewQuad in normal quadrupole
3175       The name of each quadrupole has to be unique
3176
3177   Input:
3178       none
3179
3180   Output:
3181       none
3182
3183   Return:
3184       none
3185
3186   Global variables:
3187       trace
3188
3189   Specific functions:
3190       GetElem, SetKLpar, GetKpar
3191
3192   Comments:
3193       none
3194
3195****************************************************************************/
3196void SetSkewQuad(void)
3197{
3198  FILE *fi;
3199  const char fic_skew[] = "QT-solamor_2_3.dat";
3200  int i;
3201  double theta[500]; /* array for skew quad tilt*/
3202  double b2, mKL;
3203  CellType Cell;
3204  long mOrder;
3205
3206  int nquad = 0;  /* Number of skew quadrupoles */
3207  int qlist[500];  /* Quadrupole list */
3208
3209  /* make quadrupole list */
3210  for (i = 0; i <= globval.Cell_nLoc; i++)
3211  {
3212    getelem(i, &Cell); /* get element */
3213
3214    if (Cell.Elem.Pkind == Mpole)
3215    {
3216      if (fabs(Cell.Elem.M->PBpar[2L + HOMmax]) > 0.0)
3217      {
3218        qlist[nquad] = i;
3219        nquad++;
3220        if (trace) printf("%s % f\n",Cell.Elem.PName,
3221                           Cell.Elem.M->PBpar[2L + HOMmax]);
3222      }
3223    }
3224  }
3225
3226  /* open skew quad file */
3227  if ((fi = fopen(fic_skew,"r")) == NULL)
3228  {
3229    fprintf(stdout, "Error while opening file %s \n",fic_skew);
3230    exit_(1);
3231  }
3232
3233  /* read tilt in radians */
3234  for (i = 0; i < nquad; i++)
3235  {
3236    fscanf(fi,"%le \n", &theta[i]);
3237    theta[i+1] = theta[i];
3238    i++;
3239  }
3240  fclose(fi);
3241
3242
3243  for (i = 0; i < nquad; i++)
3244  {
3245    if (trace) fprintf(stdout,"%le \n", theta[i]);
3246
3247    getelem(qlist[i], &Cell);
3248
3249    /* Get KL for a quadrupole */
3250    b2 = Cell.Elem.PL*GetKpar(Cell.Fnum, Cell.Knum, 2L);
3251
3252    mKL = b2*sin(2*theta[i]);
3253    SetKLpar(Cell.Fnum, Cell.Knum, mOrder=-2L, mKL);
3254    mKL = b2*cos(2*theta[i]);
3255    SetKLpar(Cell.Fnum, Cell.Knum, mOrder=2L, mKL);
3256
3257    if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld KL=% e, KtiltL=% e\n"
3258                ,i,
3259                Cell.Elem.PName,Cell.Fnum, Cell.Knum,
3260                Cell.Elem.M->PBpar[HOMmax+2],
3261                Cell.Elem.M->PBpar[HOMmax-2]);
3262 }
3263}
3264
3265/****************************************************************************/
3266/* void SetDecapole(void)
3267
3268   Purpose:
3269       Set decapole in horizontal correctors
3270
3271   Input:
3272       none
3273
3274   Output:
3275       none
3276
3277   Return:
3278       none
3279
3280   Global variables:
3281       trace
3282
3283   Specific functions:
3284       GetElem, SetKLpar, GetKpar
3285
3286   Comments:
3287       none
3288
3289****************************************************************************/
3290// void SetDecapole(void)
3291// {
3292//   FILE *fi;
3293//   const char fic_deca[] ="/home/nadolski/soltracy/deca.dat";
3294//   int i;
3295//   double mKL[56]; /* array for skew quad tilt*/
3296//   CellType Cell;
3297//   long mOrder=5L;
3298
3299
3300//   /* open skew quad file */
3301//   if ((fi = fopen(fic_deca,"r")) == NULL){
3302//     fprintf(stderr, "Error while opening file %s \n",fic_deca);
3303//     exit(1);
3304//   }
3305
3306//   /* read decapole strength */
3307//   for (i = 0; i < globval.hcorr; i++){
3308//     fscanf(fi,"%le \n", &mKL[i]);
3309//   }
3310//   fclose(fi);
3311
3312//   for (i = 0; i < globval.hcorr; i++){
3313//     if (trace) fprintf(stdout,"%le \n", mKL[i]);
3314
3315//     getelem(globval.hcorr_list[i], &Cell);
3316//     SetKLpar(Cell.Fnum, Cell.Knum, mOrder, mKL[i]);
3317
3318//     if (trace) printf("num= %4d name = %s Fnum = %3ld, Knum=%3ld KL=% e, KtiltL=% e\n"
3319//                 ,i,
3320//                 Cell.Elem.PName,Cell.Fnum, Cell.Knum,
3321//                 Cell.Elem.M->PBpar[HOMmax+mOrder],
3322//                 Cell.Elem.M->PBpar[HOMmax-mOrder]);
3323//  }
3324// }
3325
3326/****************************************************************************/
3327/* void MomentumAcceptance(char *MomAccFile, long deb, long fin,
3328                        double ep_min, double ep_max, long nstepp, double em_min,
3329                        double em_max, long nstepm, long nturn)
3330   Purpose:
3331        Compute momemtum acceptance along the ring, track the particle with
3332        different energy, momentum acceptance is the energy when the particle
3333        is lost or the last energy if the particle is not lost.
3334       
3335         Based on the version in tracy 2.
3336       
3337   Input:
3338       MomAccFile   file to save calculated momentum compact factor
3339       deb          first element for momentum acceptance,"debut" is beginning in French
3340       fin          last element for momentum acceptance,"fin"   is end in French
3341
3342       ep_min       minimum energy deviation for positive momentum acceptance
3343       ep_max       maximum energy deviation for positive momentum acceptance
3344       nstepp       number of energy steps for positive momentum acceptance
3345 
3346       em_min       minimum energy deviation for negative momentum acceptance
3347       em_max       maximum energy deviation for negative momentum acceptance
3348       nstepm       number of energy steps for negative momentum acceptance
3349
3350
3351       * 1 grande section droite
3352       * 13 entree premier bend
3353       * 22 sortie SX4
3354       * 41 section droite moyenne
3355       * 173 fin superperiode
3356
3357   Output:
3358       output file soleil.out : file of results
3359       output file phase.out : file of tracking results during the process
3360
3361   Return:
3362       none
3363
3364   Global variables:
3365       none
3366
3367   specific functions:
3368       set_vectorcod
3369
3370   Comments:
3371       30/06/03 add fflush(NULL) to force writing at the end to correct
3372                unexpected bug: rarely the output file is not finished
3373       31/07/03 add closed orbit a element: useful for 6D tracking
3374                delta_closed_orbite = dp(cavity)/2
3375       21/10/03 add array for vertical initial conditions using tracking
3376                removed choice of tracking: now this should be done outside
3377               
3378       23/07/10  modify the call variable to the Cell_Pass( ): j-1L --> j (L3435, L3590)
3379                 since the Cell_Pass( ) is tracking from element i0 to i1(tracy 3), and
3380                       the Cell_Pass( ) is tracking from element i0+1L to i1(tracy 2).
3381           17/04/11 add number of turn
3382        27/06/11  fix the bug of the index in the tabz and tabpz when calling Trac( );
3383                 fix the bug in the vertical closed orbit when calling Trac( ).
3384        19/07/11  add the interface to save calculated momentum compact factor in the
3385                  user defined file.
3386                  add interface for user to define the start vertical amplitude at the
3387                  entrance lattice element which is used to find the 6D closed orbit.
3388                                                                               
3389****************************************************************************/
3390void MomentumAcceptance(char *MomAccFile, long deb, long fin, 
3391                        double ep_min, double ep_max, long nstepp, double em_min, 
3392                        double em_max, long nstepm, long nturn, double  zmax)           
3393{
3394  double        dP = 0.0, dp1 = 0.0, dp2 = 0.0;
3395  long          lastpos = 0L,lastn = 0L;
3396  long          i = 0L, j = 0L, pos = 0L;
3397  CellType      Cell, Clost;
3398  double        x = 0.0, px = 0.0, z = 0.0, pz = 0.0, ctau0 = 0.0, delta = 0.0;
3399  Vector        x0;
3400  FILE          *outf2, *outf1;
3401 
3402  double        **tabz0, **tabpz0;
3403  struct tm     *newtime;  // for time
3404  Vector        codvector[Cell_nLocMax];
3405  bool          cavityflag, radiationflag;
3406  bool          trace=true; 
3407 
3408  x0.zero();
3409
3410  /* Get time and date */
3411  newtime = GetTime();
3412 
3413  /************************/
3414  /* Fin des declarations */
3415
3416  /* File opening for writing */
3417
3418  outf1 = fopen("phase.out", "w");
3419  outf2 = fopen(MomAccFile, "w");
3420
3421  fprintf(outf2,"# TRACY III -- %s \n", asctime2(newtime));
3422  fprintf(outf2,"#  i        s         dp      s_lost  name_lost \n#\n");
3423
3424  fprintf(outf1,"# TRACY III  -- %s \n", asctime2(newtime));
3425  fprintf(outf1,"#  i        x           xp            z           zp           dp          ctau\n#\n");
3426 
3427
3428  pos = deb; /* starting position or element index in the ring */
3429
3430  /***************************************************************/
3431  fprintf(stdout,"Computing initial conditions ... \n");
3432  /***************************************************************/
3433
3434  // cod search has to be done in 4D since in 6D it is zero
3435  cavityflag = globval.Cavity_on;
3436  radiationflag = globval.radiation; 
3437  globval.Cavity_on = false;  /* Cavity on/off */
3438  globval.radiation = false;  /* radiation on/off */ 
3439
3440   // Allocation of an array of pointer array
3441  tabz0  = (double **)malloc((nstepp)*sizeof(double*));
3442  tabpz0 = (double **)malloc((nstepp)*sizeof(double*));
3443  if (tabz0 == NULL || tabpz0 == NULL){
3444    fprintf(stdout,"1 out of memory \n"); return;
3445  }
3446
3447  for (i = 1L; i <= nstepp; i++){ // loop over energy
3448    // Dynamical allocation 0 to nstepp -1
3449    tabz0[i-1L]  = (double *)malloc((fin+1L)*sizeof(double));
3450    tabpz0[i-1L] = (double *)malloc((fin+1L)*sizeof(double));
3451    if (tabz0[i-1L] == NULL || tabpz0[i-1L] == NULL)
3452    {
3453      fprintf(stdout,"2 out of memory \n"); 
3454      return;
3455    }
3456
3457    // compute dP
3458    if (nstepp != 1L) 
3459      dP = ep_max - (nstepp - i)*(ep_max - ep_min)/(nstepp - 1L);
3460    else 
3461      dP = ep_max;
3462
3463    // find and store closed orbit for dP energy offset
3464    set_vectorcod(codvector, dP);
3465       
3466   // coordinates around closed orbit specially useful for 6D
3467    x0[0] = codvector[0][0];
3468    x0[1] = codvector[0][1];
3469    x0[2] = codvector[0][2] + zmax;
3470    x0[3] = codvector[0][3];
3471    x0[4] = codvector[0][4];
3472    x0[5] = codvector[0][5];
3473
3474  if (0) fprintf(stdout,"dP=% e : %e %e %e %e %e %e\n",
3475          dP,x0[0],x0[1],x0[2],x0[3],x0[4],x0[5]);
3476    // Store vertical initial conditions
3477    // case where deb is not element 1
3478    if (deb > 1L)
3479    {
3480       Cell_Pass(1L, deb - 1L, x0, lastpos); // track from 1 to deb-1L element
3481       j = deb -1L;
3482       
3483       if (lastpos != j)
3484       { // look if stable
3485         tabz0 [i- 1L][j] = 1.0;
3486         tabpz0[i- 1L][j] = 1.0;
3487       }
3488       else
3489       { // stable case
3490         tabz0 [i - 1L][j] = x0[2] - codvector[deb-1L][2];
3491         tabpz0[i - 1L][j] = x0[3] - codvector[deb-1L][3];
3492       }
3493    }
3494    else 
3495    { // case where deb is element 1
3496      j = deb - 1L;
3497      tabz0 [i - 1L][j] = x0[2] - codvector[j][2];
3498      tabpz0[i - 1L][j] = x0[3] - codvector[j][3];
3499   }
3500
3501    for (j = deb; j < fin; j++)
3502    { // loop over elements
3503      Cell_Pass(j, j, x0, lastpos);
3504    //   Cell_Pass(j -1L, j, x0, lastpos);
3505     
3506      if (lastpos != j){ // look if stable
3507        tabz0 [i - 1L][j] = 1.0;
3508        tabpz0[i - 1L][j] = 1.0;
3509      }
3510      else{ // stable case
3511        tabz0 [i - 1L][j] = x0[2] - codvector[j][2];
3512        tabpz0[i - 1L][j] = x0[3] - codvector[j][3];
3513//        fprintf(stdout,"z0= % e pz0= % e\n", tabz0 [i - 1L][j], tabpz0 [i - 1L][j]);
3514      }
3515    }
3516  }
3517
3518  globval.Cavity_on = cavityflag;
3519  globval.radiation = radiationflag;
3520
3521  /***************************************************************/
3522  fprintf(stdout,"Computing positive momentum acceptance ... \n");
3523  /***************************************************************/
3524
3525  do
3526  {
3527    getcod(dP=0.0, lastpos);       /* determine closed orbit */
3528
3529    getelem(pos,&Cell);
3530    // coordinates around closed orbit which is non zero for 6D tracking
3531    x     = Cell.BeamPos[0];
3532    px    = Cell.BeamPos[1];
3533    z     = Cell.BeamPos[2];
3534    pz    = Cell.BeamPos[3];
3535    delta = Cell.BeamPos[4];
3536    ctau0 = Cell.BeamPos[5];
3537    fprintf(stdout,"%3ld %6.4g %6.4g %6.4g %6.4g %6.4g %6.4g\n",
3538            pos, x, px, z, pz, delta, ctau0);
3539
3540    dp1 = 0.0;
3541    dp2 = 0.0;
3542    i   = 0L;
3543   
3544    do /* Tracking over nturn */
3545    {
3546      i++;
3547      dp1 = dp2;
3548     
3549      if (nstepp != 1L) 
3550        dp2= ep_max - (nstepp - i)*(ep_max - ep_min)/(nstepp - 1L);
3551      else 
3552        dp2 = ep_max; 
3553     
3554      if (trace)  printf("i=%4ld pos=%4ld dp=%6.4g\n",i,pos,dp2);
3555      if (0) fprintf(stdout,"pos=%4ld z0 =% 10.5f  pz0 =% 10.5f  \n", pos, tabz0[i-1L][pos-1L], tabpz0[i-1L][pos-1L]);
3556     
3557      Trac(x, px, z+tabz0[i-1L][pos-1L], pz+tabpz0[i-1L][pos-1L], dp2+delta , ctau0, nturn, pos, lastn, lastpos, outf1);
3558   
3559    }while (((lastn) == nturn) && (i != nstepp));
3560           
3561    if ((lastn) == nturn) 
3562      dp1 = dp2;
3563         
3564    getelem(lastpos,&Clost);
3565    getelem(pos,&Cell);
3566   
3567    fprintf(stdout,"pos=%4ld z0 =% 10.5f  pz0 =% 10.5f  \n", pos, tabz0[i-1L][pos-1L], tabpz0[i-1L][pos-1L]);
3568    fprintf(stdout,"%4ld %10.5f %10.5f %10.5f %*s\n", pos,Cell.S,dp1,Clost.S,5,Clost.Elem.PName);
3569    fprintf(outf2,"%4ld %10.5f %10.5f %10.5f %*s\n", pos,Cell.S,dp1,Clost.S,5,Clost.Elem.PName);
3570   
3571    pos++;
3572   
3573  }while(pos != fin);
3574
3575  // free memory
3576  for (i = 1L; i <= nstepp; i++){
3577    free(tabz0 [i - 1L]);
3578    free(tabpz0[i - 1L]);
3579  }
3580  free(tabz0);
3581  free(tabpz0);
3582
3583  /***************************************************************/
3584  /***************************************************************/
3585  // NEGATIVE MOMENTUM ACCEPTANCE
3586  /***************************************************************/
3587  /***************************************************************/
3588 
3589  fprintf(outf2,"\n"); /* A void line */
3590
3591  pos = deb; /* starting position in the ring */
3592 
3593  /***************************************************************/
3594  fprintf(stdout,"Computing initial conditions ... \n");
3595  /***************************************************************/
3596
3597  // cod search has to be done in 4D since in 6D it is zero
3598  cavityflag        = globval.Cavity_on;
3599  radiationflag     = globval.radiation;
3600  globval.Cavity_on = false;  /* Cavity on/off */
3601  globval.radiation = false;  /* radiation on/off */ 
3602 
3603   // Allocation of an array of pointer array
3604  tabz0  = (double **)malloc((nstepm)*sizeof(double*));
3605  tabpz0 = (double **)malloc((nstepm)*sizeof(double*));
3606  if (tabz0 == NULL || tabpz0 == NULL){
3607    fprintf(stdout,"1 out of memory \n"); return;
3608  }
3609
3610  for (i = 1L; i <= nstepm; i++){ // loop over energy
3611    // Dynamical allocation
3612    tabz0[i-1L]  = (double *)malloc((fin+1L)*sizeof(double));
3613    tabpz0[i-1L] = (double *)malloc((fin+1L)*sizeof(double));
3614    if (tabz0[i-1L] == NULL || tabpz0[i-1L] == NULL){
3615      fprintf(stdout,"2 out of memory \n"); return;
3616    }
3617
3618    // compute dP
3619    if (nstepm != 1L) {
3620      dP = em_max - (nstepm - i)*(em_max - em_min)/(nstepm - 1L);
3621    }
3622    else {     
3623      dP = em_max;
3624    }
3625    // store closed orbit
3626    set_vectorcod(codvector, dP);
3627
3628   // coordinates around closed orbit specially usefull for 6D
3629    x0[0] = codvector[0][0];
3630    x0[1] = codvector[0][1];
3631    x0[2] = codvector[0][2] + zmax;
3632    x0[3] = codvector[0][3];
3633    x0[4] = codvector[0][4];
3634    x0[5] = codvector[0][5];
3635
3636    // Store vertical initial conditions
3637    // case where deb is not element 1
3638    if (deb > 1L){
3639       Cell_Pass(1L, deb - 1L, x0, lastpos); // track from 1 to deb-1L element
3640       j = deb -1L;
3641       if (lastpos != j){ // look if stable
3642         tabz0 [i- 1L][j] = 1.0;
3643         tabpz0[i- 1L][j] = 1.0;
3644       }
3645       else{ // stable case
3646         tabz0 [i - 1L][j] = x0[2] - codvector[deb-1L][2];
3647         tabpz0[i - 1L][j] = x0[3] - codvector[deb-1L][3];
3648       }
3649    }
3650    else { // case where deb is element 1
3651      j = deb - 1L;
3652      tabz0 [i - 1L][j] = x0[2] - codvector[j][2];
3653      tabpz0[i - 1L][j] = x0[3] - codvector[j][3];
3654//      fprintf(stdout,"z0= % e pz0= % e\n", tabz0 [i - 1L][j], tabpz0 [i - 1L][j]);
3655   }
3656
3657    for (j = deb; j < fin; j++){ // loop over elements
3658      Cell_Pass(j, j, x0, lastpos);
3659     //   Cell_Pass(j -1L, j, x0, lastpos);
3660      if (lastpos != j){ // look if stable
3661        tabz0 [i - 1L][j] = 1.0;
3662        tabpz0[i - 1L][j] = 1.0;
3663      }
3664      else{ // stable case
3665        tabz0 [i - 1L][j] = x0[2] - codvector[j][2];
3666        tabpz0[i - 1L][j] = x0[3] - codvector[j][3];
3667//        fprintf(stdout,"dP= % e pos= %ld z0= % e pz0= % e\n", dP, j, tabz0 [i - 1L][j], tabpz0 [i - 1L][j]);
3668      }
3669    }
3670  }
3671
3672  globval.Cavity_on = cavityflag; 
3673  globval.radiation = radiationflag;
3674
3675  /***************************************************************/
3676  fprintf(stdout,"Computing negative momentum acceptance ... \n");
3677  /***************************************************************/
3678   
3679  do {
3680    getcod(dP=0.0, lastpos);       /* determine closed orbit */
3681
3682  getelem(pos,&Cell);
3683    // coordinates around closed orbit which is non zero for 6D tracking
3684    x     = Cell.BeamPos[0];
3685    px    = Cell.BeamPos[1];
3686    z     = Cell.BeamPos[2];
3687    pz    = Cell.BeamPos[3];
3688    delta = Cell.BeamPos[4];
3689    ctau0 = Cell.BeamPos[5];
3690    fprintf(stdout,"%3ld %6.4g %6.4g %6.4g %6.4g %6.4g %6.4g\n",
3691            pos, x, px, z, pz, delta, ctau0);
3692
3693    dp1 = 0.0;
3694    dp2 = 0.0;
3695    i   = 0L;
3696    do /* Tracking over nturn */
3697    {
3698      i++;
3699      dp1 = dp2;
3700      if (nstepm != 1L) {
3701        dp2= em_max - (nstepm - i)*(em_max - em_min)/(nstepm - 1L);
3702      }
3703      else {
3704        dp2 = em_max;
3705      }
3706      if (trace) printf("i=%4ld pos=%4ld dp=%6.4g\n",i,pos,dp2);
3707      Trac(x, px, z+tabz0[i-1L][pos-1L], pz+tabpz0[i-1L][pos-1L], dp2+delta , ctau0, nturn, pos, lastn, lastpos, outf1);
3708    }
3709    while (((lastn) == nturn) && (i != nstepm));
3710
3711    if ((lastn) == nturn) dp1 = dp2;
3712
3713    getelem(lastpos,&Clost);
3714    getelem(pos,&Cell);
3715    if (!trace)  printf("i=%4ld pos=%4ld dp=%6.4g\n",i,pos,dp2);
3716    fprintf(stdout,"pos=%4ld z0 =% 10.5f  pz0 =% 10.5f  \n", pos, tabz0[i-1L][pos-1L], tabpz0[i-1L][pos-1L]);
3717    fprintf(stdout,"%4ld %10.5f %10.5f %10.5f %*s\n", pos,Cell.S,dp1,Clost.S, 5, Clost.Elem.PName);
3718    fprintf(outf2,"%4ld %10.5f %10.5f %10.5f %*s\n", pos,Cell.S,dp1,Clost.S, 5, Clost.Elem.PName);
3719    pos++;
3720  }
3721  while(pos != fin);
3722
3723  // free memory
3724  for (i = 1L; i <= nstepp; i++){
3725    free(tabz0 [i - 1L]);
3726    free(tabpz0[i - 1L]);
3727  }
3728  free(tabz0);
3729  free(tabpz0);
3730 
3731  fflush(NULL); // force writing at the end (BUG??)
3732  fclose(outf1);
3733  fclose(outf2);
3734}
3735
3736/****************************************************************************/
3737/*void MomentumAcceptance_p(char *_MomAccFile, long deb, long fin, double ep_min,
3738                            double ep_max, long nstepp, double em_min, double em_max,
3739                            long nstepm, long nturn, double  zmax, int numprocs,int myid)
3740
3741Purpose:
3742        Parallel version of MomentumAcceptance( ).
3743        Compute momemtum acceptance along the ring, track the particle with
3744        different energy, momentum acceptance is the energy when the particle
3745        is lost or the last energy if the particle is not lost.
3746       
3747         Based on the version in tracy 2.
3748       
3749   Input:
3750       MomAccFile   file to save calculated momentum compact factor
3751       deb          first element for momentum acceptance,"debut" is beginning in French
3752       fin          last element for momentum acceptance,"fin"   is end in French
3753
3754       ep_min       minimum energy deviation for positive momentum acceptance
3755       ep_max       maximum energy deviation for positive momentum acceptance
3756       nstepp       number of energy steps for positive momentum acceptance
3757 
3758       em_min       minimum energy deviation for negative momentum acceptance
3759       em_max       maximum energy deviation for negative momentum acceptance
3760       nstepm       number of energy steps for negative momentum acceptance
3761       
3762       numprocs     number of processes used to do parallel computation.
3763       myid         process used to do parallel computation.
3764         
3765       * 1 grande section droite
3766       * 13 entree premier bend
3767       * 22 sortie SX4
3768       * 41 section droite moyenne
3769       * 173 fin superperiode
3770
3771   Output:
3772       output file soleil.out : file of results
3773       output file phase.out : file of tracking results during the process
3774
3775   Return:
3776       none
3777
3778   Global variables:
3779       none
3780
3781   specific functions:
3782       set_vectorcod
3783
3784   Comments:
3785        19/07/11 Add feature to do parallel calculation of momentum compact factor.
3786                 Merged with the version written by Mao-Sen Qiu at Taiwan light source.                                                                 
3787****************************************************************************/ 
3788void MomentumAcceptance_p(char *_MomAccFile, long deb, long fin, double ep_min, 
3789                          double ep_max, long nstepp, double em_min, double em_max, 
3790                          long nstepm, long nturn, double  zmax, int numprocs,int myid)         
3791{
3792  double        dP = 0.0, dp1 = 0.0, dp2 = 0.0;
3793  long          lastpos = 0L,lastn = 0L;
3794  long          i = 0L, j = 0L, pos = 0L;
3795  CellType      Cell, Clost;
3796  double        x = 0.0, px = 0.0, z = 0.0, pz = 0.0, ctau0 = 0.0, delta = 0.0;
3797  Vector        x0;
3798  FILE          *outf2, *outf1;
3799 
3800  double        **tabz0, **tabpz0;
3801  struct tm     *newtime;  // for time
3802  Vector        codvector[Cell_nLocMax];
3803  bool          cavityflag, radiationflag;
3804  bool          trace=true; 
3805 
3806  x0.zero();
3807
3808  // Get time and date
3809  newtime = GetTime();
3810 
3811  /************************/
3812  // Fin des declarations
3813
3814  // File opening for writing
3815  char PhaseFile[50];
3816  PhaseFile[0]='\0';
3817  sprintf(PhaseFile,"%d",myid);
3818  strcat(PhaseFile,"phase.out");
3819  //printf("%s\n",PhaseFile);
3820  outf1 = fopen(PhaseFile, "w");
3821
3822  if(myid==0)
3823  {
3824   fprintf(outf1,"# TRACY III  -- %s \n", asctime2(newtime));
3825   fprintf(outf1,"#  i        x           xp            z           zp           dp          ctau\n#\n");
3826  }
3827
3828  char MomAccFile[50];
3829  MomAccFile[0]='\0';
3830  sprintf(MomAccFile,"%d",myid);
3831  strcat(MomAccFile,_MomAccFile);
3832  printf("%s\n",MomAccFile);
3833
3834  outf2 = fopen(MomAccFile, "w"); 
3835
3836  if(myid==0)
3837  {
3838   fprintf(outf2,"# TRACY III -- %s \n", asctime2(newtime));
3839   fprintf(outf2,"#  i        s         dp      s_lost  name_lost \n#\n");
3840  }
3841
3842  // pos = deb; // starting position or element index in the ring
3843
3844  /***************************************************************/
3845  fprintf(stdout,"Computing initial conditions ... \n");
3846  /***************************************************************/
3847
3848  // cod search has to be done in 4D since in 6D it is zero
3849  cavityflag = globval.Cavity_on;
3850  radiationflag = globval.radiation; 
3851  globval.Cavity_on = false;  /* Cavity on/off */
3852  globval.radiation = false;  /* radiation on/off */ 
3853
3854   // Memory allocation. Allocation of an array of pointer array
3855  tabz0  = (double **)malloc((nstepp)*sizeof(double*));
3856  tabpz0 = (double **)malloc((nstepp)*sizeof(double*));
3857  if (tabz0 == NULL || tabpz0 == NULL){
3858    fprintf(stdout,"1 out of memory \n"); return;
3859  }
3860
3861  for (i = 1L; i <= nstepp; i++)
3862  { // loop over energy
3863    // Dynamical allocation 0 to nstepp -1
3864    tabz0[i-1L]  = (double *)malloc((fin+1L)*sizeof(double));
3865    tabpz0[i-1L] = (double *)malloc((fin+1L)*sizeof(double));
3866    if (tabz0[i-1L] == NULL || tabpz0[i-1L] == NULL)
3867    {
3868      fprintf(stdout,"2 out of memory \n"); 
3869      return;
3870    }
3871
3872    // compute dP
3873    if (nstepp != 1L) 
3874      dP = ep_max - (nstepp - i)*(ep_max - ep_min)/(nstepp - 1L);
3875    else 
3876      dP = ep_max;
3877
3878    // find and store closed orbit for dP energy offset
3879    set_vectorcod(codvector, dP);
3880       
3881   // coordinates around closed orbit specially useful for 6D
3882    x0[0] = codvector[0][0];
3883    x0[1] = codvector[0][1];
3884    x0[2] = codvector[0][2] + zmax;
3885    x0[3] = codvector[0][3];
3886    x0[4] = codvector[0][4];
3887    x0[5] = codvector[0][5];
3888
3889    if (0) fprintf(stdout,"dP=% e : %e %e %e %e %e %e\n", dP,x0[0],x0[1],x0[2],x0[3],x0[4],x0[5]);
3890
3891    // Store vertical initial conditions
3892    // case where deb is not element 1
3893    if (deb > 1L)
3894    {
3895       Cell_Pass(1L, deb - 1L, x0, lastpos); // track from 1 to deb-1L element
3896       j = deb -1L;
3897       
3898       if (lastpos != j)
3899       { // look if stable
3900         tabz0 [i- 1L][j] = 1.0;
3901         tabpz0[i- 1L][j] = 1.0;
3902       }
3903       else
3904       { // stable case
3905         tabz0 [i - 1L][j] = x0[2] - codvector[deb-1L][2];
3906         tabpz0[i - 1L][j] = x0[3] - codvector[deb-1L][3];
3907       }
3908    }
3909    else 
3910    { // case where deb is element 1
3911      j = deb - 1L;
3912      tabz0 [i - 1L][j] = x0[2] - codvector[j][2];
3913      tabpz0[i - 1L][j] = x0[3] - codvector[j][3];
3914   }
3915
3916    for (j = deb; j < fin; j++)
3917    { // loop over elements
3918      Cell_Pass(j, j, x0, lastpos);
3919    //Cell_Pass(j -1L, j, x0, lastpos);
3920     
3921      if (lastpos != j){ // look if stable
3922        tabz0 [i - 1L][j] = 1.0;
3923        tabpz0[i - 1L][j] = 1.0;
3924      }
3925      else{ // stable case
3926        tabz0 [i - 1L][j] = x0[2] - codvector[j][2];
3927        tabpz0[i - 1L][j] = x0[3] - codvector[j][3];
3928//      fprintf(stdout,"z0= % e pz0= % e\n", tabz0 [i - 1L][j], tabpz0 [i - 1L][j]);
3929      }
3930    }
3931  }
3932
3933  globval.Cavity_on = cavityflag;
3934  globval.radiation = radiationflag;
3935
3936  /***************************************************************/
3937  fprintf(stdout,"Computing positive momentum acceptance ... \n");
3938  /***************************************************************/
3939
3940//split tracking element region for each process
3941//Eace core or process calculate different region of fmap according to id number. MSChiu 2011/10/13
3942  int debN,finN;
3943  int integer,residue;
3944
3945  //the end element should not less than start element
3946if(fin < deb){
3947  printf("End element index %ld should be NOT smaller than the start element index %ld\n",fin,deb);
3948  exit_(1);
3949}
3950
3951  integer=(fin-deb+1)/numprocs;
3952  residue=(fin-deb+1)-integer*numprocs;
3953
3954  printf("myid:%d, integer:%d, resideu:%d, numprocs:%d, Nbx:%d\n",myid,integer,residue,numprocs);
3955
3956  //split tracking element region  for each process
3957  //the start element is from deb
3958  if(myid<residue)
3959    {
3960      debN=myid*(integer+1) +deb;
3961      finN=(myid+1)*(integer+1) +deb;
3962    }
3963  else
3964    {
3965      debN=residue*(integer+1)+(myid-residue)*integer +deb;
3966      finN=residue*(integer+1)+(myid+1-residue)*integer +deb;
3967    }
3968 
3969
3970  //do
3971 for(pos=debN;pos<finN;pos++) 
3972  {
3973    getcod(dP=0.0, lastpos);       // determine closed orbit
3974
3975    getelem(pos,&Cell);
3976    // coordinates around closed orbit which is non zero for 6D tracking
3977    x     = Cell.BeamPos[0];
3978    px    = Cell.BeamPos[1];
3979    z     = Cell.BeamPos[2];
3980    pz    = Cell.BeamPos[3];
3981    delta = Cell.BeamPos[4];
3982    ctau0 = Cell.BeamPos[5];
3983   
3984    fprintf(stdout,"%3ld %6.4g %6.4g %6.4g %6.4g %6.4g %6.4g\n", pos, x, px, z, pz, delta, ctau0);
3985
3986    fprintf(stdout,"%3ld %6.4g %6.4g %6.4g %6.4g %6.4g %6.4g\n", pos, globval.CODvect[0], globval.CODvect[1],globval.CODvect[2],
3987                                                                      globval.CODvect[3], globval.CODvect[4],globval.CODvect[5]);
3988 
3989    dp1 = 0.0;
3990    dp2 = 0.0;
3991    i   = 0L;
3992   
3993    do // Tracking over nturn
3994    {
3995      i++;
3996      dp1 = dp2;
3997     
3998      if (nstepp != 1L) 
3999        dp2= ep_max - (nstepp - i)*(ep_max - ep_min)/(nstepp - 1L);
4000      else 
4001        dp2 = ep_max; 
4002     
4003     // if (trace)  printf("i=%4ld pos=%4ld dp=%6.4g\n",i,pos,dp2);
4004      if (trace)
4005        printf("i=%4ld dp=%6.4g pos=%3ld %6.4g %6.4g %6.4g %6.4g %6.4g %6.4g\n", i, dp2, pos, x, px, z+tabz0[i-1L][pos-1L], pz+tabpz0[i-1L][pos-1L], dp2+delta, ctau0);
4006
4007      if (0) fprintf(stdout,"pos=%4ld z0 =% 10.5f  pz0 =% 10.5f  \n", pos, tabz0[i-1L][pos-1L], tabpz0[i-1L][pos-1L]);
4008     
4009      Trac(x, px, z+tabz0[i-1L][pos-1L], pz+tabpz0[i-1L][pos-1L], dp2+delta , ctau0, nturn, pos, lastn, lastpos, outf1);
4010   
4011    }while (((lastn) == nturn) && (i != nstepp));
4012           
4013    if ((lastn) == nturn) 
4014      dp1 = dp2;
4015         
4016    getelem(lastpos,&Clost);
4017    getelem(pos,&Cell);
4018   
4019    fprintf(stdout,"pos=%4ld z0 =% 10.5f  pz0 =% 10.5f  \n", pos, tabz0[i-1L][pos-1L], tabpz0[i-1L][pos-1L]);
4020    fprintf(stdout,"%4ld %10.5f %10.5f %10.5f %*s\n", pos, Cell.S, dp1, Clost.S, 5, Clost.Elem.PName);
4021    fprintf(outf2, "%4ld %10.5f %10.5f %10.5f %*s\n", pos, Cell.S, dp1, Clost.S, 5, Clost.Elem.PName);
4022   
4023    //    pos++;
4024   
4025  }//while(pos != fin);
4026
4027  // free memory
4028  for (i = 1L; i <= nstepp; i++)
4029  {
4030    free(tabz0 [i - 1L]);
4031    free(tabpz0[i - 1L]);
4032  }
4033  free(tabz0);
4034  free(tabpz0);
4035
4036  /***************************************************************/
4037  /***************************************************************/
4038  // NEGATIVE MOMENTUM ACCEPTANCE
4039  /***************************************************************/
4040  /***************************************************************/
4041 
4042  fprintf(outf2,"Negative\n"); // A void line
4043
4044  //  pos = deb; // starting position in the ring
4045 
4046  /***************************************************************/
4047  fprintf(stdout,"Computing initial conditions ... \n");
4048  /***************************************************************/
4049
4050  // cod search has to be done in 4D since in 6D it is zero
4051  cavityflag        = globval.Cavity_on;
4052  radiationflag     = globval.radiation;
4053  globval.Cavity_on = false;  // Cavity on/off
4054  globval.radiation = false;  // radiation on/off 
4055 
4056   // Allocation of an array of pointer array
4057  tabz0  = (double **)malloc((nstepm)*sizeof(double*));
4058  tabpz0 = (double **)malloc((nstepm)*sizeof(double*));
4059  if (tabz0 == NULL || tabpz0 == NULL){
4060    fprintf(stdout,"1 out of memory \n"); return;
4061  }
4062
4063  for (i = 1L; i <= nstepm; i++){ // loop over energy
4064    // Dynamical allocation
4065    tabz0[i-1L]  = (double *)malloc((fin+1L)*sizeof(double));
4066    tabpz0[i-1L] = (double *)malloc((fin+1L)*sizeof(double));
4067    if (tabz0[i-1L] == NULL || tabpz0[i-1L] == NULL){
4068      fprintf(stdout,"2 out of memory \n"); return;
4069    }
4070
4071    // compute dP
4072    if (nstepm != 1L) {
4073      dP = em_max - (nstepm - i)*(em_max - em_min)/(nstepm - 1L);
4074    }
4075    else {     
4076      dP = em_max;
4077    }
4078    // store closed orbit
4079    set_vectorcod(codvector, dP);
4080
4081   // coordinates around closed orbit specially usefull for 6D
4082    x0[0] = codvector[0][0];
4083    x0[1] = codvector[0][1];
4084    x0[2] = codvector[0][2] + zmax;
4085    x0[3] = codvector[0][3];
4086    x0[4] = codvector[0][4];
4087    x0[5] = codvector[0][5];
4088
4089    // Store vertical initial conditions
4090    // case where deb is not element 1
4091    if (deb > 1L){
4092       Cell_Pass(1L, deb - 1L, x0, lastpos); // track from 1 to deb-1L element
4093       j = deb -1L;
4094       if (lastpos != j){ // look if stable
4095         tabz0 [i- 1L][j] = 1.0;
4096         tabpz0[i- 1L][j] = 1.0;
4097       }
4098       else{ // stable case
4099         tabz0 [i - 1L][j] = x0[2] - codvector[deb-1L][2];
4100         tabpz0[i - 1L][j] = x0[3] - codvector[deb-1L][3];
4101       }
4102    }
4103    else { // case where deb is element 1
4104      j = deb - 1L;
4105      tabz0 [i - 1L][j] = x0[2] - codvector[j][2];
4106      tabpz0[i - 1L][j] = x0[3] - codvector[j][3];
4107//    fprintf(stdout,"z0= % e pz0= % e\n", tabz0 [i - 1L][j], tabpz0 [i - 1L][j]);
4108   }
4109
4110    for (j = deb; j < fin; j++){ // loop over elements
4111      Cell_Pass(j, j, x0, lastpos);
4112     //   Cell_Pass(j -1L, j, x0, lastpos);
4113      if (lastpos != j){ // look if stable
4114        tabz0 [i - 1L][j] = 1.0;
4115        tabpz0[i - 1L][j] = 1.0;
4116      }
4117      else{ // stable case
4118        tabz0 [i - 1L][j] = x0[2] - codvector[j][2];
4119        tabpz0[i - 1L][j] = x0[3] - codvector[j][3];
4120//        fprintf(stdout,"dP= % e pos= %ld z0= % e pz0= % e\n", dP, j, tabz0 [i - 1L][j], tabpz0 [i - 1L][j]);
4121      }
4122    }
4123  }
4124
4125  globval.Cavity_on = cavityflag; 
4126  globval.radiation = radiationflag;
4127
4128  /***************************************************************/
4129  fprintf(stdout,"Computing negative momentum acceptance ... \n");
4130  /***************************************************************/
4131   
4132  // do
4133 for(pos=debN;pos<finN;pos++)
4134{
4135    getcod(dP=0.0, lastpos);       // determine closed orbit
4136
4137    getelem(pos,&Cell);
4138    // coordinates around closed orbit which is non zero for 6D tracking
4139    x     = Cell.BeamPos[0];
4140    px    = Cell.BeamPos[1];
4141    z     = Cell.BeamPos[2];
4142    pz    = Cell.BeamPos[3];
4143    delta = Cell.BeamPos[4];
4144    ctau0 = Cell.BeamPos[5];
4145    fprintf(stdout,"%3ld %6.4g %6.4g %6.4g %6.4g %6.4g %6.4g\n", pos, x, px, z, pz, delta, ctau0);
4146
4147    dp1 = 0.0;
4148    dp2 = 0.0;
4149    i   = 0L;
4150    do // Tracking over nturn
4151    {
4152      i++;
4153      dp1 = dp2;
4154      if (nstepm != 1L) {
4155        dp2= em_max - (nstepm - i)*(em_max - em_min)/(nstepm - 1L);
4156      }
4157      else {
4158        dp2 = em_max;
4159      }
4160      if (trace)
4161        printf("i=%4ld pos=%4ld dp=%6.4g %6.4g %6.4g %6.4g %6.4g %6.4g %6.4g\n",i,pos,dp2, x, px, z+tabz0[i-1L][pos-1L], pz+tabpz0[i-1L][pos-1L], dp2+delta, ctau0);
4162      Trac(x, px, z+tabz0[i-1L][pos-1L], pz+tabpz0[i-1L][pos-1L], dp2+delta , ctau0, nturn, pos, lastn, lastpos, outf1);
4163    }
4164    while (((lastn) == nturn) && (i != nstepm));
4165
4166    if ((lastn) == nturn) dp1 = dp2;
4167
4168    getelem(lastpos,&Clost);
4169    getelem(pos,&Cell);
4170    if (!trace)  printf("i=%4ld pos=%4ld dp=%6.4g\n",i,pos,dp2);
4171    fprintf(stdout,"pos=%4ld z0 =% 10.5f  pz0 =% 10.5f  \n", pos, tabz0[i-1L][pos-1L], tabpz0[i-1L][pos-1L]);
4172    fprintf(stdout,"%4ld %10.5f %10.5f %10.5f %*s\n", pos, Cell.S, dp1, Clost.S, 5, Clost.Elem.PName);
4173    fprintf(outf2, "%4ld %10.5f %10.5f %10.5f %*s\n", pos, Cell.S, dp1, Clost.S, 5, Clost.Elem.PName);
4174    //    pos++;
4175  }
4176 //while(pos != fin);
4177
4178  // free memory
4179  for (i = 1L; i <= nstepp; i++)
4180  {
4181    free(tabz0 [i - 1L]);
4182    free(tabpz0[i - 1L]);
4183  }
4184  free(tabz0);
4185  free(tabpz0);
4186 
4187  fflush(NULL); // force writing at the end (BUG??)
4188  fclose(outf1);
4189  fclose(outf2);
4190}
4191
4192
4193/****************************************************************************/
4194/* set_vectorcod(double codvector[Cell_nLocMax][6], double dP)
4195
4196   Purpose:
4197      Store closed orbit computed for a Dp energy offset
4198
4199   Input:
4200       dP  offset energy
4201
4202   Output:
4203       codvector : closed orbit all around the ring
4204
4205   Return:
4206       none
4207
4208   Global variables:
4209       status
4210
4211   Specific functions:
4212       getcod
4213
4214   Comments:
4215       Does not work for a transfer line
4216
4217****************************************************************************/
4218void set_vectorcod(Vector  codvector[], double dP)
4219{
4220  long      k = 0L, lastpos = 0L;
4221  CellType  Cell;
4222  Vector    zerovector;
4223
4224  zerovector.zero();
4225 
4226  getcod(dP, lastpos);  /* determine closed orbit */
4227
4228 
4229  if (status.codflag == 1) { /* cod exists */
4230    for (k = 1L; k <= globval.Cell_nLoc; k++){
4231      getelem(k,&Cell);
4232      codvector[k] = Cell.BeamPos;
4233    }
4234    // cod at entrance of the ring is the one at the exit (1-periodicity)
4235    CopyVec(6L, Cell.BeamPos, codvector[0]);
4236  }
4237  else { /* nostable cod */
4238    for (k = 1L; k <= globval.Cell_nLoc; k++)
4239      codvector[k] = zerovector;
4240  }
4241}
4242
4243// LAURENT
4244/****************************************************************************/
4245/* void spectrum(long Nbx, long Nbz, long Nbtour, double xmax, double zmax,
4246   double energy, bool *status)
4247
4248   Purpose:
4249       Compute a frequency map of Nbx x Nbz points
4250       For each set of initial conditions the particle is tracked over
4251       Nbtour for an energy offset dp
4252
4253       The stepsize follows a square root law
4254
4255       Results in fmap.out
4256
4257   Input:
4258       Nbx    horizontal step number
4259       Nby    vertical step number
4260       xmax   horizontal maximum amplitude
4261       zmax   vertical maximum amplitude
4262       Nbtour number of turn for tracking
4263       energy particle energy offset
4264
4265   Output:
4266       status true if stable
4267              false otherwise
4268
4269   Return:
4270       none
4271
4272   Global variables:
4273       none
4274
4275   Specific functions:
4276       Trac_Simple, Get_NAFF
4277
4278   Comments:
4279       15/10/03 run for the diffusion: nasty patch for retrieving the closed orbit
4280
4281****************************************************************************/
4282void spectrum(long Nbx, long Nbz, long Nbtour, double xmax, double zmax,
4283              double energy, bool diffusion)
4284{
4285 FILE *xoutf, *zoutf;
4286 const char xfic[] = "xspectrum.out";
4287 const char zfic[] = "zspectrum.out";
4288 long i, j, k;
4289 #define nterm2  20
4290 double Tab[6][NTURN], fx[nterm2], fz[nterm2], fx2[nterm2], fz2[nterm2];
4291 double x = 0.0, xp = 0.0, z = 0.0, zp = 0.0;
4292 double x0 = 1e-6, xp0 = 0.0, z0 = 1e-6, zp0 = 0.0;
4293 double xstep = 0.0, zstep = 0.0;
4294 int nb_freq[2] = {0, 0};
4295 long nturn = Nbtour;
4296 bool status=true;
4297 struct tm *newtime;
4298
4299 /* Get time and date */
4300 time_t aclock;
4301 time(&aclock);                 /* Get time in seconds */
4302 newtime = localtime(&aclock);  /* Convert time to struct */
4303
4304 if (diffusion) nturn = 2*Nbtour;
4305
4306// if (trace) printf("Entering fmap ... results in %s\n\n",fic);
4307
4308 /* Opening file */
4309 if ((xoutf = fopen(xfic, "w")) == NULL) {
4310   fprintf(stdout, "fmap: error while opening file %s\n", xfic);
4311   exit_(1);
4312 }
4313
4314 if ((zoutf = fopen(zfic, "w")) == NULL) {
4315   fprintf(stdout, "fmap: error while opening file %s\n", zfic);
4316   exit_(1);
4317 }
4318
4319 fprintf(xoutf,"# TRACY II v. 2.6 -- %s -- %s \n", xfic, asctime2(newtime));
4320 fprintf(zoutf,"# TRACY II v. 2.6 -- %s -- %s \n", zfic, asctime2(newtime));
4321// fprintf(outf,"# nu = f(x) \n");
4322// fprintf(outf,"#    x[m]          z[m]           fx            fz           dfx           dfz\n");
4323
4324 if ((Nbx <= 1) || (Nbz <= 1))
4325   fprintf(stdout,"fmap: Error Nbx=%ld Nbz=%ld\n",Nbx,Nbz);
4326
4327 xp = xp0;
4328 zp = zp0;
4329
4330 xstep = xmax/sqrt((double)Nbx);
4331 zstep = zmax/sqrt((double)Nbz);
4332
4333 for (i = 0; i <= Nbx; i++) {
4334   x  = x0 + sqrt((double)i)*xstep;
4335   for (j = 0; j<= Nbz; j++) {
4336     z  = z0 + sqrt((double)j)*zstep;
4337     Trac_Simple4DCOD(x,xp,z,zp,energy,0.0,nturn,Tab,&status);
4338     if (status) {
4339      Get_NAFF(nterm2, Nbtour, Tab, fx, fz, nb_freq);
4340     }
4341     else {
4342      fx[0]  = 0.0; fz[0]  = 0.0;
4343      fx2[0] = 0.0; fz2[0] = 0.0;
4344     }
4345
4346     // printout value
4347         if (!diffusion){
4348
4349       fprintf(xoutf,"%14.6e %14.6e", x, z);
4350       fprintf(zoutf,"%14.6e %14.6e", x, z);
4351       fprintf(stdout,"%14.6e %14.6e", x, z);
4352
4353       for (k = 0; k < nb_freq[0]; k++){
4354         fprintf(xoutf," %14.6e", fx[k]);
4355         fprintf(stdout," %14.6e", fx[k]);
4356       }
4357
4358       for (k = 0; k < nb_freq[1]; k++){
4359         fprintf(zoutf," %14.6e", fz[k]);
4360         fprintf(stdout," %14.6e", fz[k]);
4361       }
4362
4363       fprintf(stdout,"\n");
4364       fprintf(xoutf,"\n");
4365       fprintf(zoutf,"\n");       
4366     }
4367//     else {
4368//       fprintf(outf,"%14.6e %14.6e %14.6e %14.6e %14.6e %14.6e\n",
4369//        x, z, fx[0], fz[0], fx[0]-fx2[0], fz[0]-fz2[0]);
4370//       fprintf(stdout,"%14.6e %14.6e %14.6e %14.6e %14.6e %14.6e\n",
4371//        x, z, fx[0], fz[0], fx[0]-fx2[0], fz[0]-fz2[0]);
4372//     }
4373   }
4374 }
4375
4376 fclose(xoutf);
4377 fclose(zoutf);
4378}
4379
4380/****************************************************************************/
4381/* void TracCO(double x, double px, double y, double py, double dp, double ctau,
4382          long nmax, long pos, long *lastn, long *lastpos, FILE *outf1)
4383
4384   Purpose:
4385      Single particle tracking
4386      Same as Trac but with respect to closed orbit
4387
4388   Input:
4389      x, px, y, py 4 transverses coordinates
4390      dp           energy offset
4391      nmax         number of turns
4392      pos          starting position for tracking
4393      aperture     global physical aperture
4394
4395
4396   Output:
4397      lastn       last n (should be nmax if  not lost)
4398      lastpos     last position in the ring
4399
4400   Return:
4401       none
4402
4403   Global variables:
4404       globval
4405
4406   specific functions:
4407       Cell_Pass
4408
4409   Comments:
4410       BUG: last printout is wrong because not at pos but at the end of the ring
4411       26/04/03 print output for phase space is for position pos now
4412
4413****************************************************************************/
4414void TracCO(double x, double px, double y, double py, double dp, double ctau,
4415            long nmax, long pos, long &lastn, long &lastpos, FILE *outf1)
4416{
4417  bool lostF; /* Lost particle Flag */
4418  Vector x1;     /* tracking coordinates */
4419  Vector2  aperture;
4420  CellType Cell;
4421
4422  aperture[0] = 1e0;
4423  aperture[1] = 1e0;
4424
4425  /* Get closed orbit */
4426  Ring_GetTwiss(true, 0.0);
4427  getcod(dp, lastpos);
4428  getelem(pos-1,&Cell);
4429
4430  if (!trace) printf("dp= % .5e %% xcod= % .5e mm zcod= % .5e mm \n",
4431             dp*1e2, Cell.BeamPos[0]*1e3, Cell.BeamPos[2]*1e3);
4432
4433  /* Tracking coordinates around the closed orbit */
4434    x1[0] =  x + Cell.BeamPos[0]; x1[1] = px   + Cell.BeamPos[1];
4435    x1[2] =  y + Cell.BeamPos[2]; x1[3] = py   + Cell.BeamPos[3];
4436    x1[4] = dp; x1[5] = ctau; // line true in 4D tracking
4437//    x1[4] = dp + Cell.BeamPos[4]; x1[5] = ctau + Cell.BeamPos[5];
4438
4439    lastn = 0;
4440    lostF = true;
4441
4442    (lastpos) = pos;
4443
4444    if (!trace) fprintf(outf1, "\n");
4445
4446    do
4447    {
4448      (lastn)++;
4449      if (!trace) { // print initial conditions
4450        fprintf(outf1, "%6ld %+10.5e %+10.5e %+10.5e %+10.5e"
4451                " %+10.5e %+10.5e \n",
4452                lastn, x1[0], x1[1], x1[2], x1[3], x1[4], x1[5]);
4453      }
4454
4455    //  Cell_Pass(pos-1L, globval.Cell_nLoc, x1, lastpos);
4456      Cell_Pass(pos, globval.Cell_nLoc, x1, lastpos);
4457      Cell_Pass(0,pos-1L, x1, lastpos);
4458    }
4459    while (((lastn) < nmax) && ((lastpos) == pos-1L));
4460
4461    if (lastpos != pos-1L)
4462    {
4463      printf("TracCO: Particle lost \n");
4464      fprintf(stdout, "turn=%6ld %+10.5g %+10.5g %+10.5g"
4465              " %+10.5g %+10.5g %+10.5g \n",
4466              lastn, x1[0], x1[1], x1[2], x1[3], x1[4], x1[5]);
4467    }
4468  }
4469
4470
4471/****************************************************************************/
4472/*   void getA4antidamping()
4473
4474   Purpose:
4475
4476   Input:
4477       none
4478
4479   Output:
4480       none
4481
4482   Return:
4483       none
4484
4485   Global variables:
4486       none
4487
4488   specific functions:
4489       none
4490
4491   Comments:
4492
4493****************************************************************************/
4494void getA4antidamping()
4495  {
4496  /* function to get A for anti damping condition */
4497  /* See publication at ALS for off momentum particle dynamics */
4498
4499  CellType Cell;
4500  int qlist[320];
4501  int nquad=0, i;
4502  double A = 0.0;
4503
4504  for (i = 0; i <= globval.Cell_nLoc; i++)
4505  {
4506    getelem(i, &Cell); /* get element */
4507
4508    if (Cell.Elem.Pkind == Mpole)
4509    {
4510      if (fabs(Cell.Elem.M->PBpar[2L + HOMmax]) > 0.0)
4511      {
4512        qlist[nquad] = i;
4513        nquad++;
4514        if (!trace) printf("%s % f\n",Cell.Elem.PName, Cell.Elem.M->PBpar[2L + HOMmax]);
4515      }
4516    }
4517  }
4518  fprintf(stdout,"Nombre de quadrupoles %d\n", nquad);
4519
4520  Ring_GetTwiss(true, 0.0);
4521  for (i = 0; i < nquad; i++)
4522  {
4523    getelem(qlist[i],&Cell);
4524    fprintf(stdout,"%d Name = %s L=%g A= %g etax=%g \n", i, Cell.Elem.PName, Cell.Elem.PL, A,Cell.Eta[0]);
4525    A += Cell.Elem.PL*2.0*(Cell.Elem.M->PBpar[2L + HOMmax]*Cell.Eta[0])*
4526                       (Cell.Elem.M->PBpar[2L + HOMmax]*Cell.Eta[0]);
4527    i++;
4528  }
4529  fprintf(stdout,"A= %g\n", A*1.706);
4530  }
4531
4532
4533/****************************************************************************/
4534/* void fmapfull(long Nbx, long Nbz, long Nbtour, double xmax, double zmax,
4535   double energy, bool *status)
4536
4537   Purpose:
4538       Compute a frequency map of Nbx x Nbz points
4539       For each set of initial conditions the particle is tracked over
4540       Nbtour for an energy offset dp
4541
4542       The stepsize follows a square root law
4543
4544       Results in fmap.out
4545
4546   Input:
4547       Nbx    horizontal step number
4548       Nby    vertical step number
4549       xmax   horizontal maximum amplitude
4550       zmax   vertical maximum amplitude
4551       Nbtour number of turn for tracking
4552       energy particle energy offset
4553
4554   Output:
4555       status true if stable
4556              false otherwise
4557
4558   Return:
4559       none
4560
4561   Global variables:
4562       none
4563
4564   Specific functions:
4565       Trac_Simple, Get_NAFF
4566
4567   Comments:
4568       Note enough precision for diffusion
4569
4570****************************************************************************/
4571#define NTERM  10
4572void fmapfull(long Nbx, long Nbz, long Nbtour, double xmax, double zmax,
4573              double energy, bool diffusion)
4574{
4575 FILE * outf;
4576 const char fic[] = "fmapfull.out";
4577 int i, j, k;
4578 double Tab[DIM][NTURN], Tab0[DIM][NTURN];
4579 double fx[NTERM], fz[NTERM], fx2[NTERM], fz2[NTERM];
4580 double x  = 0.0, xp = 0.0, z = 0.0, zp = 0.0;
4581 double x0 = 1e-6, xp0 = 0.0, z0 = 1e-6, zp0 = 0.0;
4582 double xstep = 0.0, zstep = 0.0;
4583 int nb_freq[2] = {0, 0};
4584 double nux1[NTERM], nuz1[NTERM],nux2[NTERM], nuz2[NTERM];
4585 long nturn = Nbtour;
4586 bool status=true;
4587 struct tm *newtime;
4588 char name[14];
4589
4590 /* Get time and date */
4591 time_t aclock;
4592 time(&aclock);                 /* Get time in seconds */
4593 newtime = localtime(&aclock);  /* Convert time to struct */
4594
4595 if (diffusion) nturn = 2*Nbtour;
4596
4597 if (trace) printf("Entering fmap ... results in %s\n\n",fic);
4598
4599 /* Opening file */
4600 if ((outf = fopen(fic, "w")) == NULL) {
4601   fprintf(stdout, "fmapfull: error while opening file %s\n", fic);
4602   exit_(1);
4603 }
4604
4605 fprintf(outf,"# TRACY II v. 2.6 -- %s -- %s \n", fic, asctime2(newtime));
4606 fprintf(outf,"# Frequency map freq = f(x,z) \n");
4607 fprintf(outf,"#    x[m]          z[m]          ");
4608
4609 for (k = 0; k < NTERM; k++){
4610   sprintf(name,"f%dx           ",k);
4611   fprintf(outf,"%s",name);
4612 }
4613 for (k = 0; k < NTERM; k++){
4614   sprintf(name,"f%dz           ",k);
4615   fprintf(outf,"%s",name);
4616 }
4617
4618 if (!diffusion){
4619   fprintf(outf,"\n");
4620 }
4621 else{
4622   for (k = 0; k < NTERM; k++){
4623     sprintf(name,"df%dx          ",k);
4624     fprintf(outf,"%s",name);
4625   }
4626   for (k = 0; k < NTERM; k++){
4627     sprintf(name,"df%dz          ",k);
4628     fprintf(outf,"%s",name);
4629   }
4630   fprintf(outf,"\n");
4631 }
4632
4633 if ((Nbx <= 1) || (Nbz <= 1))
4634   fprintf(stdout,"fmap: Error Nbx=%ld Nbz=%ld\n",Nbx,Nbz);
4635
4636 xp = xp0;
4637 zp = zp0;
4638
4639 xstep = xmax/sqrt((double)Nbx);
4640 zstep = zmax/sqrt((double)Nbz);
4641
4642 for (i = 0; i <= Nbx; i++) {
4643   x  = x0 + sqrt((double)i)*xstep;
4644   for (j = 0; j<= Nbz; j++) {
4645     z  = z0 + sqrt((double)j)*zstep;
4646     Trac_Simple4DCOD(x,xp,z,zp,energy,0.0,nturn,Tab,&status);
4647
4648     if (status) {
4649       Get_NAFF(NTERM, Nbtour, Tab, fx, fz, nb_freq);
4650
4651       for (k = 0; k < nb_freq[0]; k++){
4652         nux1[k] = fx[k];
4653       }
4654       for (k = 0; k < nb_freq[1]; k++){
4655         nuz1[k] = fz[k];
4656       }
4657       for (k = nb_freq[0]; k < NTERM; k++){
4658         nux1[k] = 0.0;
4659       }
4660       for (k = nb_freq[1]; k < NTERM; k++){
4661         nuz1[k] = 0.0;
4662       }         
4663       if (diffusion){
4664         Get_Tabshift(Tab,Tab0,Nbtour,Nbtour); // shift data for second round NAFF
4665         Get_NAFF(NTERM, Nbtour, Tab0, fx2, fz2, nb_freq); // gets frequency vectors
4666
4667         for (k = 0; k < nb_freq[0]; k++){
4668           nux2[k] = fx2[k];
4669         }
4670         for (k = 0; k < nb_freq[1]; k++){
4671           nuz2[k] = fz2[k];
4672         }
4673         for (k = nb_freq[0]; k < NTERM; k++){
4674           nux2[k] = 0.0;
4675         }
4676         for (k = nb_freq[1]; k < NTERM; k++){
4677           nuz2[k] = 0.0;
4678         }
4679       }
4680     }
4681     else {
4682      for (k = 0; k < NTERM; k++){
4683        nux1[k] = 0.0;
4684        nuz1[k] = 0.0;
4685        nux2[k] = 0.0;
4686        nuz2[k] = 0.0;
4687      }
4688     }
4689     
4690     // printout value
4691     if (!diffusion){
4692       fprintf(outf,"%14.6e %14.6e ", x, z);
4693       for (k = 0; k < NTERM; k++){
4694         fprintf(outf,"%14.6e ", nux1[k]);
4695       }
4696       for (k = 0; k < NTERM; k++){
4697         fprintf(outf,"%14.6e ", nuz1[k]);
4698       }
4699       fprintf(outf,"\n");
4700//       fprintf(stdout,"%14.6e %14.6e %14.6e %14.6e\n", x, z, nux1, nuz1);
4701     }
4702     else {
4703       fprintf(outf,"%14.6e %14.6e ", x, z);
4704       for (k = 0; k < NTERM; k++){
4705         fprintf(outf,"%14.6e ", nux1[k]);
4706       }
4707       for (k = 0; k < NTERM; k++){
4708         fprintf(outf,"%14.6e ", nuz1[k]);
4709       }
4710       for (k = 0; k < NTERM; k++){
4711         fprintf(outf,"%14.6e ", nux2[k]);
4712       }
4713       for (k = 0; k < NTERM; k++){
4714         fprintf(outf,"%14.6e ", nuz2[k]);
4715       }
4716       fprintf(outf,"\n");
4717//       fprintf(stdout,"%14.6e %14.6e %14.6e %14.6e %14.6e %14.6e\n",
4718//        x, z, nux1, nuz1, fx[0]-fx2[0], fz[0]-fz2[0]);
4719     }
4720   }
4721 }
4722
4723 fclose(outf);
4724}
4725#undef NTERM
4726
4727/****************************************************************************/
4728/* void Dyna(long Nbx, long Nbz, long Nbtour, double xmax, double zmax,
4729   double energy, bool *status)
4730
4731   Purpose:
4732       Compute a frequency map of Nbx x Nbz points
4733       For each set of initial conditions the particle is tracked over
4734       Nbtour for an energy offset dp
4735
4736       The stepsize follows a square root law
4737
4738       Results in fmap.out
4739
4740   Input:
4741       Nbx    horizontal step number
4742       Nby    vertical step number
4743       xmax   horizontal maximum amplitude
4744       zmax   vertical maximum maplitude
4745       Nbtour number of turn for tracking
4746       energy particle energy offset
4747
4748   Output:
4749       status true if stable
4750              false otherwise
4751
4752   Return:
4753       none
4754
4755   Global variables:
4756       none
4757
4758   Specific functions:
4759       Trac_Simple, Get_NAFF
4760
4761   Comments:
4762       none
4763
4764****************************************************************************/
4765#define NTERM2  2
4766void Dyna(long Nbx, long Nbz, long Nbtour, double xmax, double zmax,
4767               double energy, bool diffusion)
4768{
4769  FILE * outf;
4770  const char fic[] = "dyna.out";
4771  long i, j;
4772  double Tab[6][NTURN], fx[NTERM2], fz[NTERM2];
4773  double x = 0.0, xp = 0.0, z = 0.0, zp = 0.0;
4774  double x0 = 1e-6, xp0 = 0.0, z0 = 1e-6, zp0 = 0.0;
4775  double xstep = 0.0, zstep = 0.0;
4776  int nb_freq[2] = {0, 0};
4777  long nturn = Nbtour;
4778  bool status=true;
4779  struct tm *newtime;
4780
4781  /* Get time and date */
4782  newtime = GetTime();
4783
4784  if (diffusion) nturn = 2*Nbtour;
4785
4786  if (trace) printf("Entering fmap ... results in %s\n\n",fic);
4787
4788  /* Opening file moustache */
4789  if ((outf = fopen(fic, "w")) == NULL)
4790  {
4791    fprintf(stdout, "fmap: error while opening file %s\n", fic);
4792    exit_(1);
4793  }
4794
4795  fprintf(outf,"# TRACY II v. 2.6 -- %s -- %s \n", fic, asctime2(newtime));
4796  fprintf(outf,"# nu = f(x) \n");
4797  fprintf(outf,"#    x[m]          z[m]           fx            fz \n");
4798
4799  if ((Nbx <= 1) || (Nbz <= 1))
4800    fprintf(stdout,"fmap: Error Nbx=%ld Nbz=%ld\n",Nbx,Nbz);
4801
4802  xp = xp0;
4803  zp = zp0;
4804
4805  xstep = xmax/sqrt((double)Nbx);
4806  zstep = zmax/sqrt((double)Nbz);
4807
4808  for (i = 0; i <= Nbx; i++) {
4809    x  = x0 + sqrt((double)i)*xstep;
4810    for (j = 0; j<= Nbz; j++) {
4811      z  = z0 + sqrt((double)j)*zstep;
4812      Trac_Simple4DCOD(x,xp,z,zp,energy,0.0,nturn,Tab,&status);
4813      if (status) Get_NAFF(NTERM2, Nbtour, Tab, fx, fz, nb_freq);
4814      else {
4815       fx[0] = 0.0; fz[0] = 0.0;
4816      }
4817      fprintf(outf,"%14.6e %14.6e %14.6e %14.6e %d\n", x, z, fx[0], fz[0], status);
4818      fprintf(stdout,"%14.6e %14.6e %14.6e %14.6e %d\n", x, z, fx[0], fz[0], status);
4819      if (diffusion) {
4820        if (status) Get_NAFF(NTERM2, Nbtour, Tab, fx, fz, nb_freq);
4821        fprintf(outf,"%14.6e %14.6e %14.6e %14.6e %d\n", x, z, fx[0], fz[0], status);
4822        fprintf(stdout,"%14.6e %14.6e %14.6e %14.6e %d\n", x, z, fx[0], fz[0], status);
4823      }
4824    }
4825  }
4826
4827  xp = xp0;
4828  zp = zp0;
4829
4830  for (i = 0; i <= Nbx; i++)  {
4831    x  = x0 - sqrt((double)i)*xstep;
4832    for (j = 0; j<= Nbz; j++) {
4833      z  = z0 + sqrt((double)j)*zstep;
4834      Trac_Simple4DCOD(x,xp,z,zp,energy,0.0,nturn,Tab,&status);
4835      if (status) Get_NAFF(NTERM2, Nbtour, Tab, fx, fz, nb_freq);
4836      else {
4837       fx[0] = 0.0; fz[0] =0.0;
4838      }
4839      fprintf(outf,"%14.6e %14.6e %14.6e %14.6e %d\n", x, z, fx[0], fz[0], status);
4840      fprintf(stdout,"%14.6e %14.6e %14.6e %14.6e %d\n", x, z, fx[0], fz[0], status);
4841      if (diffusion) {
4842        if (status) Get_NAFF(NTERM2, Nbtour, Tab, fx, fz, nb_freq);
4843        fprintf(outf,"%14.6e %14.6e %14.6e %14.6e\n", x, z, fx[0], fz[0]);
4844        fprintf(stdout,"%14.6e %14.6e %14.6e %14.6e\n", x, z, fx[0], fz[0]);
4845      }
4846    }
4847  }
4848 
4849  fclose(outf);
4850}
4851
4852/****************************************************************************/
4853/* void Phase2(long pos, double x,double xp,double y, double yp,double energy, double ctau,
4854               long Nbtour)
4855
4856   Purpose:
4857       Compute 6D phase space at position pos (=element number in the lattice )
4858       Results in phase.out
4859
4860   Input:
4861       x, xp, y, yp, energy, ctau starting position
4862       Nbtour turn number
4863
4864   Output:
4865       none
4866
4867   Return:
4868       none
4869
4870   Global variables:
4871       trace
4872
4873   Specific functions:
4874       Trac_Simple, Get_NAFF
4875
4876   Comments:
4877       none
4878
4879****************************************************************************/
4880void Phase2(long pos, double x,double px,double y, double py,double energy,
4881            double ctau, long Nbtour)
4882{
4883  FILE *outf;
4884  const char fic[] = "phase2.out";
4885  long lastpos = 0,lastn = 0;
4886  struct tm *newtime;
4887
4888  /* Get time and date */
4889  newtime = GetTime();
4890
4891  lastpos = pos;
4892
4893  if ((outf = fopen(fic, "w")) == NULL) {
4894    fprintf(stdout, "Phase: error while opening file %s\n", fic);
4895    exit_(1);
4896  }
4897
4898  fprintf(outf,"# TRACY II v. 2.6 -- %s -- %s \n", fic, asctime2(newtime));
4899  fprintf(outf,"# Phase Space \n");
4900  fprintf(outf,
4901  "# num         x           xp             z            zp           dp          ctau\n");
4902
4903  trace = true;
4904  Trac(x,px,y,py,energy,ctau, Nbtour,pos, lastn, lastpos, outf);
4905  fclose(outf);
4906}
4907
4908void Phase3(long pos, double x,double px,double y, double py,double energy,
4909            double ctau, long Nbtour)
4910{
4911  FILE *outf;
4912  const char  *fic="phase3.out";
4913  long        lastpos = 0,lastn = 0;
4914  struct tm   *newtime;
4915  Vector      x1;
4916 
4917  /* Get time and date */
4918  newtime = GetTime();
4919
4920  lastpos = pos;
4921
4922  if ((outf = fopen(fic, "w")) == NULL) {
4923    fprintf(stdout, "Phase: error while opening file %s\n", fic);
4924    exit_(1);
4925  }
4926
4927  fprintf(outf,"# TRACY II v. 2.6 -- %s -- %s \n", fic, asctime2(newtime));
4928  fprintf(outf,"# Phase Space \n");
4929  fprintf(outf,
4930  "# num         x           xp             z            zp           dp          ctau\n");
4931
4932  trace = true;
4933  x1[0] = x;   x1[1] = px;     x1[2] = y;
4934  x1[3] = py;  x1[4] = energy; x1[5] = ctau; 
4935  Cell_Pass(0L, pos-1L, x1, lastpos);
4936
4937  x  = x1[0];       px= x1[1];   y = x1[2];
4938  py = x1[3];  energy = x1[4]; ctau =x1[5];
4939 
4940  Trac(x,px,y,py,energy,ctau, Nbtour, pos, lastn, lastpos, outf);
4941  fclose(outf);
4942}
4943
4944/****************************************************************************/
4945/* void Coupling_Edwards_Teng(void)
4946
4947   Purpose:
4948
4949       Compute the oneturn matrix in the uncoupled frame using
4950       the coupled matrix.
4951
4952       Deduce the projected emittance using the invariant given
4953       by GetEmittance.
4954       
4955       Source:
4956       Parametrization of linear coupled motion in periodic system
4957       by D.A. Edwards and L.C. Teng
4958       PAC73                   
4959
4960       Let be T the oneturn matrix, I the 2x2 identity matrix
4961       We search for a basis where the system is uncoupled:
4962                                -1                                -1
4963         ( M n )  (  Icos(phi) D sin(phi) ) ( A 0 ) ( Icos(phi) -D sin(phi) )
4964      T =(     ) =(                       ) (     ) (                       )
4965         ( m N )  ( -Dsin(phi)  Icos(phi) ) ( 0 B ) ( Dsin(phi)   Icos(phi) )
4966               -1
4967      T = R U R
4968         
4969                                         ( alpha1  beta1 )   
4970      A = Icos(mu1) + J1sin(mu1)  w/ J1 =(               )
4971                                         (-gamma1 -alpha1)
4972
4973                                         ( alpha2  beta2 )
4974      B = Icos(mu2) + J2sin(mu2)  w/ J2 =(               )
4975                                         (-gamma2 -alpha2)
4976
4977                   2             2     2             2  T
4978      Given V = (<u >, <uu'>, <u' >, <v >, <uu'>, <v' >)                                 
4979                   2             2     2             2  T
4980      and   X = (<x >, <xx'>, <x' >, <z >, <zz'>, <z' >)
4981
4982      Then X = U2T V where U2T if constucted using the uncoupling R matrix
4983     
4984   Input:
4985       none
4986
4987   Output:
4988       none
4989
4990   Return:
4991       none
4992
4993   Global variables:
4994       globval
4995
4996   Specific functions:
4997       getelem
4998       GetEmittance
4999
5000   Comments:
5001       22/06/03 Now works even if coupling is null
5002       Should be generalized in 6D
5003       17/07/03 use of M_PI instead of pi
5004       22/03/04 save status cavity/radiation and restore it at the end
5005       28/07/10 modified for tracy 3   
5006****************************************************************************/           
5007void Coupling_Edwards_Teng(void)
5008{
5009  int i,j;
5010  bool chroma=true, trace=false;
5011  bool radiationflag, cavityflag;
5012  double dP      = 0.0;
5013  double diffcmu = 0.0,   /* cos(mu1) - cos(mu2)*/
5014         c2phi   = 0.0,   /* cos(2*phi) */
5015         s2phi   = 0.0,   /* sin(2*phi) */
5016         phi     = 0.0,
5017         tphi    = 0.0,   /* tan(phi) */
5018         cphi    = 0.0,   /* cos(phi) */
5019         sphi    = 0.0;   /* sin(phi) */
5020         
5021 Matrix  M, N, m, n, D, A, B, R, S;
5022 Matrix  Rinv, Dinv, nm, MminusN, tS, tn, U2T, dummy, T, U, Sigma;
5023 Vector V; 
5024
5025 
5026  double W1 = 0.0, W2 = 0.0;
5027  double alpha_1 = 0.0, beta1 = 0.0, gamma1 = 0.0, nu1 = 0.0, epsilon1 = 0.0;
5028  double alpha_2 = 0.0, beta2 = 0.0, gamma2 = 0.0, nu2 = 0.0, epsilon2 = 0.0;
5029  double alpha_3 = 0.0, beta3 = 0.0, gamma3 = 0.0, epsilon3 = 0.0;
5030 
5031 
5032  /* initialization to unit matrix */
5033  ZeroMat(6L, M);
5034  ZeroMat(6L, N);
5035  ZeroMat(6L, m);
5036  ZeroMat(6L, n);
5037  ZeroMat(6L, D);
5038  ZeroMat(6L, Dinv);
5039  ZeroMat(6L, A);
5040  ZeroMat(6L, B);
5041  ZeroMat(6L, nm);
5042  ZeroMat(6L, MminusN);
5043  ZeroMat(6L, tn);
5044  ZeroMat(6L, tS);
5045  ZeroMat(6L, S);
5046  ZeroMat(6L, dummy);
5047  UnitMat(6L, U2T);
5048  UnitMat(6L, R);
5049  UnitMat(6L, Rinv);
5050
5051  /* Build up symplectic S matrix */
5052  S[0][1] = 1.0; S[1][0] = -1.0;
5053
5054  /* Compute invariants */
5055  GetEmittance(globval.cav, true);
5056 
5057 
5058  /* Set everything to 4D integrator */
5059  radiationflag        = globval.radiation;
5060  cavityflag           = globval.Cavity_on; 
5061  globval.MatMeth      = false;    /* matrix method */
5062  globval.Cavity_on    = false;    /* Cavity on/off */
5063  globval.radiation    = false;    /* radiation on/off */
5064  globval.emittance    = false;    /* emittance  on/off */
5065  globval.pathlength   = false;    /* Path lengthening computation */
5066 
5067  /* Compute Oneturn matrix and store it into globval.OneTurnMat*/
5068  Ring_GetTwiss(chroma=false, dP=0e0);
5069//  printglob();
5070
5071  /* Copy the oneturn matrix into the Edwards and Teng Form */
5072  /*     
5073      T = ( M n )
5074          ( m N )
5075   */
5076
5077
5078  /* Compute and get Twiss parameters */
5079  for (i = 0; i <= 1; i ++)
5080  {
5081    for (j = 0; j <= 1; j ++)
5082    {
5083        M[i][j] = globval.OneTurnMat[i][j];
5084        N[i][j] = globval.OneTurnMat[i+2][j+2];
5085        m[i][j] = globval.OneTurnMat[i+2][j];
5086        n[i][j] = globval.OneTurnMat[i][j+2];
5087    }
5088  }
5089//  fprintf(stdout,"M "); prtmat(2L,M);
5090//  fprintf(stdout,"N ");prtmat(2L,N);
5091
5092  CopyMat(2L, M, MminusN);
5093  SubMat(2L,N,MminusN);
5094//  fprintf(stdout,"M-N ");  prtmat(2L,MminusN);
5095  CopyMat(2L, m, nm);
5096  MulLMat(2l, n, nm);
5097
5098  /*                                                       -1/2
5099                         1        (     2 det(m) + Tr(nm) )
5100  cos(mu1) - cos(mu2) =  -Tr(M-N) ( 1 + ----------------- )
5101                         2        (      (0.5Tr(M-N))**2  )
5102  */
5103  diffcmu = 0.5*TrMat(2L,MminusN)*sqrt(1.0 + (2.0*DetMat(2L,m) + TrMat(2L,nm))/
5104                                      (0.25*TrMat(2L,MminusN)*TrMat(2L,MminusN)));
5105  /* cos(2phi) */
5106  c2phi   = 0.5*TrMat(2L,MminusN)/diffcmu;
5107
5108  /* sin(2phi) */
5109  s2phi   = sqrt(1.0-c2phi*c2phi);
5110
5111  phi     = 0.5*atan(s2phi/c2phi);
5112
5113  /* tan(phi), cos(phi), sin(phi) */
5114  tphi    = tan(phi);
5115  cphi    = cos(phi);
5116  sphi    = sin(phi);
5117
5118  /* Compute D matrix */
5119  /*                      ~~
5120   *                 m + SnS
5121   *  D = - ----------------------------
5122   *         (cos(mu1)-cos(mu2)) sin(2phi)
5123   */
5124  if (fabs(phi) > 1e-12)
5125  {    /* D is  defined and D is inversible ortherwise set to matrix null */
5126    CopyMat(2L, n, tn);
5127    TpMat(2L,tn);
5128    CopyMat(2L, S, tS);
5129    TpMat(2l,tS);
5130    CopyMat(2L, tS, dummy);
5131
5132    MulLMat(2l, tn, dummy);
5133    MulLMat(2l, S, dummy);
5134    AddMat(2L, m, dummy);
5135    MulcMat(2L, -1.0/diffcmu/s2phi ,dummy);
5136    CopyMat(2L, dummy, D);
5137
5138    if (TrMat(4L,D) < 0.0)
5139    { /* Trace of D has to remain positive */
5140      phi = - phi;
5141      MulcMat(2L, -1.0 ,D);
5142      tphi = -tphi;
5143      sphi = -sphi;
5144    }
5145 
5146    /*  Compute A matrix   */
5147    /*          -1         */
5148    /* A = M - D mtan(phi) */
5149     CopyMat(2L, D, Dinv);
5150     if(!InvMat(2L, Dinv)) fprintf(stdout,"Matrix D is singular\n");
5151  //  fprintf(stdout,"Dinv matrix "); prtmat(4L, Dinv);
5152
5153    CopyMat(2L, m, dummy);
5154  //  fprintf(stdout,"m matrix "); prtmat(4L, dummy);
5155    MulcMat(2L, -tphi ,dummy);
5156  //  fprintf(stdout,"-tphim matrix "); prtmat(4L, dummy);
5157    MulLMat(2l, Dinv, dummy);
5158  //  fprintf(stdout,"-tphi Dinv m matrix "); prtmat(4L, dummy);
5159    AddMat(2L,M,dummy);
5160    CopyMat(2L, dummy, A);
5161
5162    /* Compute B matrix */
5163    /* B = N +Dntan(phi) */
5164    CopyMat(2L, n, dummy);
5165    MulcMat(2L, tphi ,dummy);
5166    MulLMat(2l, D, dummy);
5167    AddMat(2L,N,dummy);
5168    CopyMat(2L, dummy, B);
5169
5170    /* Build up the R matrix */
5171    /*                    -1
5172     *      (  Icos(phi) D sin(phi) )
5173     *   T =(                       )
5174     *      ( -Dsin(phi)  Icos(phi) )
5175     */
5176    MulcMat(4L, cphi ,R);
5177    CopyMat(2L, D, dummy);
5178    MulcMat(4L, -sphi , dummy);
5179    for (i = 0; i <= 1; i ++)
5180      for (j = 0; j <= 1; j ++)
5181        R[i+2][j] = dummy[i][j];
5182    CopyMat(2L, Dinv, dummy);
5183    MulcMat(4L, sphi , dummy);
5184    for (i = 0; i <= 1; i ++)
5185      for (j = 0; j <= 1; j ++)
5186        R[i][j+2] = dummy[i][j];
5187
5188    CopyMat(4L, R, Rinv);
5189    if(!InvMat(4L, Rinv)) fprintf(stdout,"Matrix R is singular\n"); 
5190
5191    /* Build up uncoupled matrix */
5192    UnitMat(6L, U);
5193    CopyMat(2L, A, U);
5194    for (i = 0; i <= 1; i ++)
5195      for (j = 0; j <= 1; j ++)
5196        U[i+2][j+2] = B[i][j];
5197    if (trace) {fprintf(stdout,"Uncoupled matrix "); prtmat(4L, U);}
5198
5199    CopyMat(4L, Rinv, T);
5200    MulLMat(4L, U, T);
5201    MulLMat(4L, R, T);
5202    /* for checking, back to T */
5203    if (trace) {fprintf(stdout,"Coupled matrix "); prtmat(4L, T);}
5204
5205
5206    /* Build up transformation matrix for sigma terms from uncoupled to coupled frame */
5207    /* R is the decoupling matrix computed from Edwards' and Teng's decomposition */
5208    /* From R. Nagaoka's notes */
5209    U2T[0][0] = R[0][0]*R[0][0];
5210    U2T[0][1] = 2.0*R[0][0]*R[0][1];
5211    U2T[0][2] = R[0][1]*R[0][1];
5212    U2T[0][3] = R[0][2]*R[0][2];
5213    U2T[0][4] = 2.0*R[0][1]*R[0][3];
5214    U2T[0][5] = R[0][3]*R[0][3];
5215
5216    U2T[1][0] = R[0][0]*R[1][0];
5217    U2T[1][1] = R[0][0]*R[1][1] + R[0][1]*R[1][0];
5218    U2T[1][2] = R[0][1]*R[1][1];
5219    U2T[1][3] = R[0][2]*R[1][2];
5220    U2T[1][4] = R[0][1]*R[1][3] + R[0][3]*R[1][2];
5221    U2T[1][5] = R[0][3]*R[1][3];
5222
5223    U2T[2][0] = R[1][0]*R[1][0];
5224    U2T[2][1] = 2.0*R[1][0]*R[1][1];
5225    U2T[2][2] = R[1][1]*R[1][1];
5226    U2T[2][3] = R[1][2]*R[1][2];
5227    U2T[2][4] = 2.0*R[1][2]*R[1][3];
5228    U2T[2][5] = R[1][3]*R[1][3];
5229
5230    U2T[3][0] = R[2][0]*R[2][0];
5231    U2T[3][1] = 2.0*R[2][0]*R[2][1];
5232    U2T[3][2] = R[2][1]*R[2][1];
5233    U2T[3][3] = R[2][2]*R[2][2];
5234    U2T[3][4] = 2.0*R[2][2]*R[2][3];
5235    U2T[3][5] = R[2][3]*R[2][3];
5236
5237    U2T[4][0] = R[2][0]*R[3][0];
5238    U2T[4][1] = R[2][0]*R[3][1] + R[2][1]*R[3][0];
5239    U2T[4][2] = R[2][1]*R[3][1];
5240    U2T[4][3] = R[2][2]*R[3][2];
5241    U2T[4][4] = R[2][2]*R[3][3] + R[2][3]*R[3][2];
5242    U2T[4][5] = R[2][3]*R[3][3];
5243
5244    U2T[5][0] = R[3][0]*R[3][0];
5245    U2T[5][1] = 2.0*R[3][0]*R[3][1];
5246    U2T[5][2] = R[3][1]*R[3][1];
5247    U2T[5][3] = R[3][2]*R[3][2];
5248    U2T[5][4] = 2.0*R[3][2]*R[3][3];
5249    U2T[5][5] = R[3][3]*R[3][3];
5250
5251    if (trace) {fprintf(stdout,"R "); prtmat(4L,R);}
5252    if (trace) {fprintf(stdout,"U2T"); prtmat(6L, U2T);}
5253
5254  }
5255  else { /* no coupling */
5256    fprintf(stdout,"\nThere is no coupling ...\n");
5257    CopyMat(2L, M, A);
5258    CopyMat(2L, N, B);       
5259  }
5260 
5261//  fprintf(stdout,"Sigma "); prtmat(6L, globval.ElemMat[0]);
5262
5263//  V[0] = globval.ElemMat[1][0][0];
5264//  V[1] = globval.ElemMat[1][0][1];
5265//  V[2] = globval.ElemMat[1][1][1];
5266//  V[3] = globval.ElemMat[1][2][2];
5267//  V[4] = globval.ElemMat[1][2][3];
5268//  V[5] = globval.ElemMat[1][3][3];
5269
5270  /* Compute Twiss parameter in the uncoupled frame */
5271  /* Mode 1*/
5272  nu1    = globval.TotalTune[0];
5273  alpha_1 = (A[0][0]-A[1][1])/sin(2.0*M_PI*nu1);
5274  beta1  =  A[0][1]/sin(2.0*M_PI*nu1);
5275  gamma1 = -A[1][0]/sin(2.0*M_PI*nu1);
5276 
5277  /* Mode 2*/
5278  nu2    = globval.TotalTune[1];
5279  alpha_2 = (B[0][0]-B[1][1])/sin(2.0*M_PI*nu2);
5280  beta2  =  B[0][1]/sin(2.0*M_PI*nu2);
5281  gamma2 = -B[1][0]/sin(2.0*M_PI*nu2);
5282
5283  /* Build up sigma matrix in uncoupled frame */
5284  ZeroMat(6L,Sigma);
5285  /* Mode 1 */
5286  epsilon1    =  globval.eps[0];
5287  Sigma[0][0] =  beta1*epsilon1;
5288  Sigma[1][1] =  gamma1*epsilon1;
5289  Sigma[0][1] = -alpha_1*epsilon1;
5290  Sigma[1][0] =  Sigma[0][1];
5291
5292  /* Mode 2 */
5293  epsilon2    =  globval.eps[1];
5294  Sigma[2][2] =  beta2*epsilon2;
5295  Sigma[3][3] =  gamma2*epsilon2;
5296  Sigma[2][3] = -alpha_2*epsilon2;
5297  Sigma[3][2] =  Sigma[2][3];
5298
5299  /* Mode 3 */
5300  epsilon3    =  globval.eps[2];
5301  Sigma[4][4] =  beta3*epsilon3;
5302  Sigma[5][5] =  gamma3*epsilon3;
5303  Sigma[4][5] = -alpha_3*epsilon3;
5304  Sigma[5][4] =  Sigma[4][5];
5305 
5306//  fprintf(stdout,"Uncoupled sigma  "); prtmat(4L, Sigma);
5307
5308  V[0] = Sigma[0][0];
5309  V[1] = Sigma[0][1];
5310  V[2] = Sigma[1][1];
5311  V[3] = Sigma[2][2];
5312  V[4] = Sigma[2][3];
5313  V[5] = Sigma[3][3];
5314
5315  if (!trace)
5316  {   
5317    fprintf(stdout,"**************************************\n");
5318    fprintf(stdout,"nu1    = % 10.6f beta1 = % 10.6f\n",globval.TotalTune[0],beta1);
5319    fprintf(stdout,"alpha_1 = % 10.6f gamma1= % 10.6f\n",alpha_1,gamma1);
5320    fprintf(stdout,"nu2    = % 10.6f beta2 = % 10.6f\n",globval.TotalTune[1],beta2);
5321    fprintf(stdout,"alpha_2 = % 10.6f gamma2= % 10.6f\n",alpha_2,gamma2);
5322    fprintf(stdout,"**************************************\n");
5323  }
5324 
5325  /* Build up invariant: should be the same as invariant given by globval.eps*/
5326  W1 = sqrt(V[0]*V[2] - V[1]*V[1]);
5327  W2 = sqrt(V[3]*V[5] - V[4]*V[4]);
5328
5329  /*** Print results */
5330  if (!trace)
5331  {
5332   fprintf(stdout,"Coupling using Edwards' and Teng's formalism\n");
5333   fprintf(stdout,"cos(mu1)-cos(mu2) = % 10.6f cos(2*phi) = % 10.6f sin(2*phi) = % 10.6f\n",
5334           diffcmu,c2phi,s2phi);
5335   fprintf(stdout,"phi = % 10.6f \n", 0.5*atan(s2phi/c2phi));
5336   fprintf(stdout,"Invariant in local coordinates:  W1 = % 10.6e, W2 = % 10.6e, W2/W1 = %10.6e\n",
5337           W1, W2, W2/W1);
5338  }
5339 
5340  if (trace){ 
5341  fprintf(stdout,"Symplectic matrix D whose derterminant is % 10.6f ", DetMat(2L,D));
5342  prtmat(2L,D);
5343  fprintf(stdout,"Symplectic matrix A whose derterminant is % 10.6f ", DetMat(2L,A));
5344  prtmat(2L,A);
5345  fprintf(stdout,"Symplectic matrix B whose derterminant is % 10.6f ", DetMat(2L,B));
5346  prtmat(2L,B);
5347  fprintf(stdout,"Symplectic matrix R whose derterminant is % 10.6f ", DetMat(4L,R));
5348  prtmat(4L,R);
5349  }
5350
5351  /* Transform the sigma matrix from uncoupled frame to coupled frame */
5352//  PrintVec(6L, V);
5353  LinTrans(6L,U2T,V);
5354//  PrintVec(6L, V);
5355
5356  /* Build up projected emittances */
5357  W1 = sqrt(V[0]*V[2] - V[1]*V[1]);
5358  W2 = sqrt(V[3]*V[5] - V[4]*V[4]);
5359
5360  // store result and restore tracking mode 4D or 6D
5361
5362  globval.epsp[0]    = W1;
5363  globval.epsp[1]    = W2;
5364  globval.Cavity_on  = cavityflag;       /* Cavity on/off */
5365  globval.radiation  = radiationflag;    /* radiation on/off */ 
5366 
5367
5368  if (!trace)
5369  {
5370    fprintf(stdout,"Projected emittances:            Ex = % 10.6e, Ez = % 10.6e, Ez/Ex = %10.6e\n",
5371            W1, W2, W2/W1);
5372    fprintf(stdout,"**************************************\n");
5373  } 
5374 }
5375
5376
5377/****************************************************************************/
5378/* void PhaseLongitudinalHamiltonien(void)
5379
5380   Purpose:
5381       Compute longitudinal phase space from analytical model
5382                                                         2              3
5383                                (                   delta          delta  )
5384      H(phi,delta) =    omegaRF*(dCoC delta + alpha1----- + alpha2*-----  )
5385                                (                     2              3    )
5386
5387                       eVRF (                                               )
5388                     - -----( cos(phi) - cos(phis) + (phi - phis) sin(phis) )
5389                        ET  (                                               )
5390                       
5391
5392      Integration method Ruth integrator H(phi, delta) = A(delta) + B(phi)
5393     
5394   Parameters:   
5395       omegaRF RF frequency/2pi
5396       eVRF    RF voltage in electron volt
5397       phis    synchronous phase
5398       alpha1  first order momentum compaction factor
5399       alpha2  second order momentum compaction factor
5400       dCoC    betatron path lengthening
5401
5402   Input:
5403       none
5404               
5405   Output:
5406       longitudinale.out
5407
5408   Return:
5409       none
5410
5411   Global variables:
5412       trace
5413
5414   Specific functions:
5415       PassA, PassB, Hsynchrotron
5416
5417   Comments:
5418       none
5419
5420****************************************************************************/
5421/* SOLEIL value for SOLAMOR2 */
5422#define alpha1 4.38E-4
5423#define alpha2 4.49E-3
5424#define dCoC  0E-6
5425#define phis  -0.238
5426#define E 2.75E3
5427#define eVRF 4
5428#define T 1.181E-6
5429#define omegaRF 352.202E6
5430
5431void PhaseLongitudinalHamiltonien(void)
5432{
5433  long i,j;
5434  const double t = T;        // To get a one turn map
5435  double phi, delta, H0;
5436  long imax = 1000L,         // turn number
5437       jmax = 25L;          // starting condition number
5438
5439  /* Constant stepsize for Ruth's and Forest's Integrator */
5440  /* Laskar's integrator is not a good idea here, since the correction factor is
5441     not integrable */
5442  const double D1 = 0.675603595979829E0;
5443        const double D2 =-0.175603595979829E0;
5444        const double C2 = 0.135120719195966E1;
5445        const double C3 =-0.170241438391932E1;
5446 
5447  FILE *outf;
5448  const char fic[] = "longitudinal.out";
5449  struct tm *newtime;
5450
5451  /* Get time and date */
5452  time_t aclock;
5453  time(&aclock);                 /* Get time in seconds */
5454  newtime = localtime(&aclock);  /* Convert time to struct */
5455
5456  if ((outf = fopen(fic, "w")) == NULL)
5457  {
5458    fprintf(stdout, "PhaseLongitudinalHamiltonien: error while opening file %s\n", fic);
5459    exit_(1);
5460  }
5461   
5462  printf("Last stable orbit %f\n", acos(1.0-T*E/eVRF*Hsynchrotron(0.0,-0.098))); 
5463
5464  fprintf(outf,"# TRACY II v. 2.6  -- %s \n", asctime2(newtime));
5465  fprintf(outf,"#  i          ctau              dp             DH/H               H \n#\n");
5466
5467  for (j = 0L; j < jmax; j++)
5468  { 
5469    phi = 0.061417777*j; delta = 0.0001;
5470    H0 = Hsynchrotron(phi,delta);
5471    fprintf(outf,"%4ld % 16.8f % 16.8f % 16.8e % 16.8f\n",0L,fmod(phi,2.0*M_PI)*0.8512/2.0/M_PI,delta, 0.0, H0);
5472
5473    for (i = 0L; i < imax; i++){
5474  // Leap Frog integrator
5475  //    PassA(&phi, delta, t*0.5);
5476  //    PassB(phi, &delta, t);
5477  //    PassA(&phi, delta, t*0.5);
5478  // 4th order symplectic integrator
5479      PassA(&phi, delta, t*D1);
5480      PassB(phi, &delta, t*C2);
5481      PassA(&phi, delta, t*D2);
5482      PassB(phi, &delta, t*C3);
5483      PassA(&phi, delta, t*D2);
5484      PassB(phi, &delta, t*C2);
5485      PassA(&phi, delta, t*D1);
5486      fprintf(outf,"%4ld % 16.8f % 16.8f % 16.8e % 16.8f\n",i,fmod(phi,2.0*M_PI)*0.8512/2.0/M_PI,
5487              delta,(H0-Hsynchrotron(phi,delta))/H0,Hsynchrotron(phi,delta));
5488    }
5489      fprintf(outf,"\n");
5490  }
5491  fclose(outf);     
5492}
5493
5494
5495/****************************************************************************/
5496/* void PassA(double *phi, double delta0, double step)
5497
5498   Purpose:
5499       Integrate exp(step*liederivativeof(H(delta,phi))
5500                                                         2              3
5501                                (                   delta          delta  )
5502      H(phi,delta) =    omegaRF*(dCoC delta + alpha1----- + alpha2*-----  )
5503                                (                     2              3    )
5504
5505
5506   parameters:
5507       omegaRF RF frequency/2pi
5508       eVRF    RF voltage in electron volt
5509       phis    synchronous phase
5510       alpha1  first order momentum compaction factor
5511       alpha2  second order momentum compaction factor
5512       dCoC    betatron path lengthening
5513
5514   Input:
5515       phi, delta coordinates
5516       step stepsize for integration
5517
5518   Output:
5519       phi new phase after t=step
5520
5521   Return:
5522       none
5523
5524   Global variables:
5525       trace
5526
5527   Specific functions:
5528       none
5529
5530   Comments:
5531       none
5532
5533****************************************************************************/
5534void PassA(double *phi, double delta0, double step)
5535{
5536  *phi -= omegaRF*2.0*M_PI*(dCoC + alpha1*delta0 + alpha2*delta0*delta0)*step;
5537}
5538
5539/****************************************************************************/
5540/* void PassB(double phi0, double *delta, double step)
5541
5542   Purpose:
5543       Integrate exp(step*liederivativeof(H(delta,phi))
5544
5545                       eVRF (                                               )
5546      H(phi,delta) = - -----( cos(phi) - cos(phis) + (phi - phis) sin(phis) )
5547                        ET  (                                               )
5548
5549
5550   parameters:
5551       omegaRF RF frequency/2pi
5552       eVRF    RF voltage in electron volt
5553       phis    synchronous phase
5554       alpha1  first order momentum compaction factor
5555       alpha2  second order momentum compaction factor
5556       dCoC    betatron path lengthening
5557
5558   Input:
5559       phi, delta coordinates
5560       step stepsize for integration
5561
5562   Output:
5563       phi new phase after t=step
5564
5565   Return:
5566       none
5567
5568   Global variables:
5569       trace
5570
5571   Specific functions:
5572       none
5573
5574   Comments:
5575       none
5576
5577****************************************************************************/
5578void PassB(double phi0, double *delta, double step)
5579{
5580  *delta += eVRF/E/T*(sin(phi0) - sin(phis))*step;
5581}
5582
5583/****************************************************************************/
5584/* double Hsynchrotron(double phi, double delta)
5585
5586   Purpose:
5587       Compute Hamiltonian
5588                                                         2              3
5589                                (                   delta          delta  )
5590      H(phi,delta) =    omegaRF*(dCoC delta + alpha1----- + alpha2*-----  )
5591                                (                     2              3    )
5592
5593                       eVRF (                                               )
5594                     - -----( cos(phi) - cos(phis) + (phi - phis) sin(phis) )
5595                        ET  (                                               )
5596
5597
5598   Input:
5599       omegaRF RF frequency/2pi
5600       eVRF    RF voltage in electron volt
5601       phis    synchronous phase
5602       alpha1  first order momentum compaction factor
5603       alpha2  second order momentum compaction factor
5604       dCoC    betatron path lengthening
5605
5606   Output:
5607       none
5608
5609   Return:
5610       Hamiltonian computed in phi and delta
5611
5612   Global variables:
5613       none
5614
5615   Specific functions:
5616       none
5617       
5618   Comments:
5619       none
5620
5621****************************************************************************/
5622double Hsynchrotron(double phi, double delta)
5623{
5624  double H = 0.0;
5625 
5626  H  = omegaRF*2.0*M_PI*(dCoC*delta + alpha1*delta*delta/2.0 + alpha2*delta*delta*delta/3.0);
5627  H -= eVRF/E/T*(cos(phi) - cos(phis) + (phi-phis)*sin(phis));
5628  return H;
5629}
5630
5631
5632double EnergySmall(double *X, double irho)
5633{
5634 double A, B;
5635 double h = irho;
5636
5637 A = (1.0+h*X[0])*(X[1]*X[1]+X[3]*X[3])/2.0/(1.0+X[4]);
5638 B = -h*X[4]*X[0]+h*h*X[0]*X[0]/0.5;
5639 return (A+B);
5640}
5641
5642double EnergyDrift(double *X)
5643{
5644 double A;
5645
5646 A = (X[1]*X[1]+X[3]*X[3])/2.0/(1.0+X[4]);
5647 return (A);
5648}
5649
5650/****************************************************************************/
5651/* void Enveloppe2(double x, double px, double y, double py, double dp, double nturn)
5652
5653   Purpose:
5654       Diagnosis for tracking
5655       Used only for debuging
5656       Print particle coordinates after each element over 1 single turn
5657
5658   Input:
5659       x, px, y, py, dp starting conditions for tracking
5660
5661   Output:
5662       none
5663
5664   Return:
5665       none
5666
5667   Global variables:
5668       trace
5669
5670   Specific functions:
5671       Trac_Simple, Get_NAFF
5672
5673   Comments:
5674       none
5675
5676****************************************************************************/
5677void Enveloppe2(double x, double px, double y, double py, double dp, double nturn)
5678{
5679  Vector x1; /* Tracking coordinates */
5680  long lastpos = globval.Cell_nLoc;
5681  FILE *outf;
5682  const char fic[] = "enveloppe2.out";
5683  int i,j ;
5684  CellType Cell;
5685  /* Array for Enveloppes */
5686  double Envxp[Cell_nLocMax], Envxm[Cell_nLocMax];
5687  double Envzp[Cell_nLocMax], Envzm[Cell_nLocMax];
5688
5689
5690  /* Get cod the delta = energy*/
5691  getcod(dp, lastpos);
5692//  /* initialization to chromatic closed orbit */
5693//  for (i = 0; i<= globval.Cell_nLoc; i++)
5694//  {
5695//   getelem(i, &Cell);
5696//   Envxm[i] = Cell.BeamPos[0];   Envxp[i] = Cell.BeamPos[0];
5697//   Envzm[i] = Cell.BeamPos[2];   Envzp[i] = Cell.BeamPos[2];
5698//  }
5699
5700  printf("xcod=%.5e mm zcod=% .5e mm \n",
5701         globval.CODvect[0]*1e3, globval.CODvect[2]*1e3);
5702
5703  if ((outf = fopen(fic, "w")) == NULL) {
5704    fprintf(stdout, "Enveloppe: error while opening file %s\n", fic);
5705    exit_(1);
5706  }
5707
5708  x1[0] =  x + globval.CODvect[0]; x1[1] = px + globval.CODvect[1];
5709  x1[2] =  y + globval.CODvect[2]; x1[3] = py + globval.CODvect[3];
5710  x1[4] = dp; x1[5] = 0e0;
5711
5712  fprintf(outf,"# s       envx(+)       envx(-)       envz(+)       envz(-)     delta \n");
5713
5714  for (i = 0; i< globval.Cell_nLoc; i++)
5715  {/* loop over full ring: one turn for intialization */
5716
5717    getelem(i,&Cell);
5718    Cell_Pass(i,i+1, x1, lastpos);
5719    if (lastpos != i+1)
5720    {
5721     printf("Unstable motion ...\n"); exit_(1);
5722    }
5723
5724    Envxp[i] = x1[0]; Envxm[i] = x1[0]; Envzp[i] = x1[2]; Envzm[i] = x1[2];
5725  }
5726
5727  for (j = 1; j < nturn; j++) {
5728    /* loop over full ring */
5729   for (i = 0; i<= globval.Cell_nLoc; i++) {
5730 
5731      getelem(i, &Cell);
5732      Cell_Pass(i, i+1, x1, lastpos);
5733      if (lastpos != i+1)
5734      {
5735       printf("Unstable motion ...\n"); exit_(1);
5736      }
5737      if (x1[0] >= Envxp[i]) Envxp[i] = x1[0];
5738      if (x1[0] <= Envxm[i]) Envxm[i] = x1[0];
5739      if (x1[2] >= Envzp[i]) Envzp[i] = x1[2];
5740      if (x1[2] <= Envzm[i]) Envzm[i] = x1[2];
5741      }
5742  }
5743
5744  for (i = 0; i<= globval.Cell_nLoc; i++)
5745  {
5746    getelem(i,&Cell);
5747    fprintf(outf,"%6.2f % .5e % .5e % .5e % .5e % .5e\n",
5748            Cell.S, Envxp[i],Envxm[i],Envzp[i],Envzm[i],dp);
5749  }
5750}
5751
5752/****************************************************************************/
5753/* double get_RFVoltage(const int Fnum)
5754
5755   Purpose:
5756       Get RF voltage of family Fnum
5757
5758   Input:
5759       Fnum: family name
5760
5761   Output:
5762       none
5763
5764   Return:
5765       RF voltage
5766
5767   Global variables:
5768       none
5769       
5770   Specific functions:
5771       none
5772       
5773   Comments:
5774       10/2010  by L.Nadolski
5775****************************************************************************/
5776double get_RFVoltage(const int Fnum){
5777
5778    double V_RF = 0.0;
5779    bool prt = false;
5780
5781  V_RF = Cell[Elem_GetPos(Fnum, 1)].Elem.C->Pvolt; //RF voltage in Volts
5782  if (prt) fprintf(stdout, "RF voltage of cavity %s is %f MV \n",
5783    Cell[Elem_GetPos(Fnum, 1)].Elem.PName, V_RF/1e6);
5784  return V_RF;
5785}
5786
5787/****************************************************************************/
5788/* void set_RFVoltage(const int Fnum, const double V_RF)
5789
5790   Purpose:
5791       Set RF voltage to the first kid in the family Fnum
5792
5793   Input:
5794       Fnum: family name
5795
5796   Output:
5797       none
5798
5799   Return:
5800       RF voltage
5801
5802   Global variables:
5803       none
5804       
5805   Specific functions:
5806       none
5807       
5808   Comments:
5809       10/2010  by L.Nadolski
5810****************************************************************************/
5811void set_RFVoltage(const int Fnum, const double V_RF){
5812
5813  int k, n = 0;
5814 
5815 
5816  n = GetnKid(Fnum);
5817  bool prt = false;
5818 
5819  for (k=1; k <=n; k++){
5820    Cell[Elem_GetPos(Fnum, k)].Elem.C->Pvolt = V_RF; // in Volts
5821  }
5822  if(prt)
5823  fprintf(stdout, "Setting cavity %s to %f MV \n",
5824  Cell[Elem_GetPos(Fnum, 1)].Elem.PName, V_RF/1e6);
5825}
5826
5827
5828/****************************************************************************************************/
5829/* void ReadFieldErr(const char *FieldErrorFile)
5830
5831   Purpose:
5832       Read multipole errors from a file
5833       
5834        The input format of the file is:
5835       
5836        seed   radom_number ; this set is optional, and only works for the rms error
5837       
5838        keyWords  sys/rms  raduis when the field error is meausred "r0", field error order "n",
5839                           field error component "Bn", field error component "An"; "n","Bn,""An",...
5840             
5841   Input:
5842       
5843
5844   Output:
5845       none
5846
5847   Return:
5848       
5849
5850   Global variables:
5851       none
5852       
5853   Specific functions:
5854       none
5855       
5856   Comments:
5857       10/2010  Written by Jianfeng Zhang
5858       01/2011  Fix the bug for reading the end of line symbol "\n" , "\r",'\r\n'
5859                at different operation system
5860       04/2011  Change the set of 'seed' for rms error in file, now it's mandatory.     
5861*****************************************************************************************************/
5862void ReadFieldErr(const char *FieldErrorFile) 
5863{ 
5864  bool  rms, set_rnd = false;
5865  char    in[max_str], name[max_str],keywrd[max_str], *prm;
5866  char    *line;
5867  int     n = 0;    /* field error order*/
5868  int     LineNum = 0;
5869  int     seed_val; // random seed number for the rms error
5870  double  Bn = 0.0, An = 0.0, r0 = 0.0; /* field error components and radius when the field error is measured */
5871  /* conversion number from A to T.m for soleil*/
5872  double  _convHcorr = 8.14e-4,_convVcorr = 4.642e-4, _convQt = 93.83e-4;
5873  FILE    *inf;
5874 
5875 const bool  prt = false;
5876
5877  inf = file_read(FieldErrorFile);
5878
5879  printf("\n");
5880  /* read lines*/
5881  while (line=fgets(in, max_str, inf)) {
5882 
5883  /* kill preceding whitespace generated by "table" key
5884        or "space" key, but leave \n
5885        so we're guaranteed to have something*/
5886     while(*line == ' ' || *line == '\t') {
5887       line++;
5888     }   
5889   
5890    /* count line number for debug*/
5891    LineNum++;
5892   
5893    /* check the line is whether comment line or null line*/
5894    if (strstr(line, "#") == NULL && strcmp(line,"\n") != 0 &&
5895         strcmp(line,"\r") != 0 &&strcmp(line,"\r\n") != 0) {
5896         
5897       
5898        sscanf(line, "%s", name); 
5899       
5900        if (strcmp("seed", name) == 0) { // the line to set random seed
5901          sscanf(line, "%*s %d", &seed_val); 
5902          printf("ReadFieldErr: setting random seed to %d\n", seed_val);
5903          set_rnd = true;
5904          iniranf(seed_val); 
5905      } else{//line to set (n Bn An sequence)
5906       
5907        /*read and assign the key words and measure radius*/
5908          sscanf(line, " %*s %s %lf",keywrd, &r0);
5909          if (prt) printf("\nsetting <%s> multipole error to: %-5s r0 = %7.1le\n",keywrd,name,r0);
5910         
5911          rms = (strcmp("rms", keywrd) == 0)? true : false;
5912          if (rms && !set_rnd) { 
5913              printf("ReadFieldErr: seed not defined\n");
5914              exit(1);
5915          }
5916                 
5917          // skip first three parameters
5918          strtok(line, " \t");
5919          strtok(NULL, " \t");
5920          strtok(NULL, " \t");
5921       
5922          /* read the end of line symbol '\n','\r','\r\n' at different operation system*/
5923          while ((prm = strtok(NULL, " \t")) != NULL && strcmp(prm, "\n") != 0 &&
5924               strcmp(prm, "\r") != 0 && strcmp(prm, "\r\n") != 0) {
5925               
5926            /* read and assign n Bn An*/
5927            sscanf(prm, "%d", &n);
5928            prm = get_prm(); /*move the pointer to the next block of the line, delimiter is table key */
5929            sscanf(prm, "%lf", &Bn);
5930            prm = get_prm(); 
5931            sscanf(prm, "%lf", &An);
5932         
5933            if (prt)
5934              printf(" n = %2d, Bn = %9.1e, An = %9.1e\n", n, Bn, An);
5935         
5936             
5937            /* set multipole errors to horizontal correctors of soleil ring*/
5938            if(strcmp("hcorr", name) == 0)
5939              AddCorrQtErr_fam(fic_hcorr,globval.hcorr,_convHcorr,keywrd,r0,n,Bn,An);
5940            /* set multipole errors to vertical correctors of soleil ring*/
5941           else if(strcmp("vcorr", name) == 0)
5942             AddCorrQtErr_fam(fic_vcorr,globval.vcorr,_convVcorr,keywrd,r0,n,Bn,An);
5943            /* set multipole errors to skew quadrupoles of soleil ring*/
5944             else if(strcmp("qt", name) == 0)
5945               AddCorrQtErr_fam(fic_skew,globval.qt,_convQt,keywrd,r0,n,Bn,An);   
5946            else
5947            /* set errors for other multipole*/
5948              AddFieldErrors(name,keywrd, r0, n, Bn, An) ;
5949        }     
5950    }//end of read the (n Bn An) sequence
5951 
5952  //end of the line
5953  }else
5954      continue;
5955     // printf("%s", line);
5956  }
5957
5958  fclose(inf);
5959}
5960
5961/***********************************************************************
5962void AddFieldErrors(const char *name, const char *keywrd,const double r0,
5963                    const int n, const double Bn, const double An)
5964                   
5965   Purpose:
5966       Add field error of the elements with the same type or single element,
5967       with the previous value, and then  the summation value replaces
5968       the previous value.
5969   
5970   Input:
5971      name         type name or element name
5972      keyword      "rms" or "sys"
5973                   "rms":  random  multipole error
5974                           "sys":  systematic multipole error
5975      r0           radius at which error is measured, error field is relative
5976                   to the design field strength when r0 !=0
5977      n            order of the error
5978      Bn           relative B component for the n-th error
5979      An           relative A component for the n-th error
5980 
5981     
5982   Output:
5983      None
5984     
5985  Return:
5986      None
5987     
5988  Global variables
5989      None
5990   
5991  Specific functions:
5992     None   
5993     
5994 Comments:
5995     10/2010  Written by Jianfeng Zhang
5996**********************************************************************/
5997void AddFieldErrors(const char *name,const char *keywrd, const double r0,
5998                    const int n, const double Bn, const double An) 
5999{
6000  int     Fnum = 0;
6001
6002  if (strcmp("all", name) == 0) {
6003    printf("all: not yet implemented\n");
6004  } else if (strcmp("dip", name) == 0) {
6005    AddFieldValues_type(Dip,keywrd, r0, n, Bn, An);
6006  } else if (strcmp("quad", name) == 0) {
6007    AddFieldValues_type(Quad, keywrd,r0, n, Bn, An);
6008  } else if (strcmp("sext", name) == 0) {
6009    AddFieldValues_type(Sext, keywrd, r0, n, Bn, An);
6010  } else {/*add error to elements*/
6011    Fnum = ElemIndex(name);
6012    if(Fnum > 0)
6013      AddFieldValues_fam(Fnum,keywrd, r0, n, Bn, An);
6014    else 
6015      printf("SetFieldErrors: undefined element %s\n", name);
6016  }
6017}
6018
6019
6020/***********************************************************************
6021void SetFieldValues_type(const int N, const char *keywrd, const double r0,
6022                         const int n, const double Bn, const double An)
6023                         
6024   Purpose:
6025       Add the field error of the upright multipole with the design order "type"
6026       with the previous value, and then the summation value replaces the previous value.
6027   Input:
6028      N            type name
6029      keywrd       "rms" or "sys"
6030                   "rms":  random  multipole error
6031                   "sys":  systematic multipole error   
6032      r0           radius at which error is measured, error field is relative
6033                   to the design field strength when r0 != 0
6034                   if r0 == 0, the Bn and An are absolute value.
6035      n            order of the error
6036      Bn           relative B component of  n-th error
6037      An           relative A component of  n-th error
6038           
6039
6040     
6041   Output:
6042      None
6043     
6044  Return:
6045      None
6046     
6047  Global variables
6048      None
6049   
6050  Specific functions:
6051     None   
6052     
6053 Comments:
6054     14/10/2010  Written by Jianfeng Zhang
6055     
6056     Only works for soleil lattice, since the Q2/Q7, QP2a,b/QP7a,b are
6057     long quadrupoles, which have different multipole errors from other
6058     short quadrupoles
6059**********************************************************************/
6060void AddFieldValues_type(const int N, const char *keywrd, const double r0,
6061                         const int n, const double Bn, const double An)
6062{
6063  double  bnL = 0.0, anL = 0.0, KLN = 0.0;
6064    int   k = 0;
6065
6066      // find the strength for multipole
6067      for(k = 1; k <= globval.Cell_nLoc; k++)
6068      {
6069        //only set upright multipole, NOT set skew multipole(skew quadrupole,etc)
6070        if ((Cell[k].Elem.Pkind == Mpole) && Cell[k].Elem.M->n_design == N && Cell[k].Elem.M->PdTpar == 0)
6071        { 
6072          //find the integrated design field strength
6073          if(N == 1)
6074            KLN = Cell[k].Elem.PL*Cell[k].Elem.M->Pirho; /*dipole angle*/
6075          else 
6076            KLN = GetKLpar(Cell[k].Fnum, Cell[k].Knum, N);/*other multipoles*/
6077           
6078           
6079          //absolute integrated multipole error strength
6080          if (r0 == 0){ 
6081            bnL = Bn;
6082            anL = An;
6083          }else{
6084            bnL = Bn/pow(r0, n-N)*KLN; 
6085            anL = An/pow(r0, n-N)*KLN;
6086          }
6087           
6088         
6089          //NOT add the multipole errors of short quadrupole to long quadrupole qp2 & qp7 of soleil ring
6090            // for the lattice with quadrupoles which are cut into two halves
6091          if(N == 2 && strncmp(Cell[k].Elem.PName,"qp2",3)==0)
6092            Add_bnL_sys_elem(Cell[k].Fnum, Cell[k].Knum,keywrd, n, 0, 0);
6093          else if(N == 2 && strncmp(Cell[k].Elem.PName,"qp7",3)==0)
6094            Add_bnL_sys_elem(Cell[k].Fnum, Cell[k].Knum, keywrd, n, 0, 0);
6095            // for the lattice with full quadrupoles
6096          else if(N == 2 && strncmp(Cell[k].Elem.PName,"q2",2)==0)
6097            Add_bnL_sys_elem(Cell[k].Fnum, Cell[k].Knum, keywrd, n, 0, 0);
6098          else if(N == 2 && strncmp(Cell[k].Elem.PName,"q7",2)==0)
6099            Add_bnL_sys_elem(Cell[k].Fnum, Cell[k].Knum, keywrd, n, 0, 0);
6100          else
6101          //add errors to multipoles except qp2, qp7
6102             Add_bnL_sys_elem(Cell[k].Fnum, Cell[k].Knum, keywrd,n, bnL,anL);   
6103      } 
6104  } 
6105 
6106}
6107/***********************************************************************
6108void AddFieldValues_fam(const int Fnum, const char *keywrd, const double r0,
6109                        const int n, const double Bn, const double An)
6110                         
6111   Purpose:
6112       add field error of all the kids in a family, with the previous value,
6113       and then the summation value replaces the previous value.
6114   
6115   Input:
6116      Fnum            family name
6117      keywrd       "rms" or "sys"
6118                   "rms":  random  multipole error
6119                   "sys":  systematic multipole error   
6120      r0              radius at which error is measured
6121                      for the case of r0 ???????
6122                     
6123      n               order of the error
6124      Bn              relative B component for the n-th error
6125      An              relative A component for the n-th error
6126           
6127
6128     
6129   Output:
6130      None
6131     
6132  Return:
6133      None
6134     
6135  Global variables
6136      None
6137   
6138  Specific functions:
6139     None   
6140     
6141 Comments:
6142     10/2010  Written by Jianfeng Zhang
6143**********************************************************************/
6144void AddFieldValues_fam(const int Fnum, const char *keywrd, const double r0,
6145                        const int n, const double Bn, const double An)
6146{
6147  int     loc = 0, ElemNum = 0, N = 0, k = 0;
6148  double  bnL = 0.0, anL = 0.0, KLN = 0.0;
6149
6150  loc = Elem_GetPos(Fnum, 1); /*element index of first kid*/
6151  N = Cell[loc].Elem.M->n_design;/*design field order*/
6152 
6153
6154       // find the integrated design field strength for multipole
6155           if (Cell[loc].Elem.M->n_design == 1)
6156           KLN = Cell[loc].Elem.PL*Cell[loc].Elem.M->Pirho; /* dipole angle */
6157           else 
6158           KLN = GetKLpar(Cell[loc].Fnum, Cell[loc].Knum, N);/* other multipole*/
6159           
6160           /* absolute integrated field strength*/
6161           if (r0 == 0){ //?????????
6162            bnL = Bn;
6163            anL = An;
6164          }else{
6165           bnL = Bn/pow(r0, n-N)*KLN; 
6166           anL = An/pow(r0, n-N)*KLN;
6167          } 
6168           //add absolute multipole field error for the family
6169           for(k = 1; k <= GetnKid(Fnum); k++){
6170             ElemNum = Elem_GetPos(Fnum, k);  /*get the element index*/
6171             Add_bnL_sys_elem(Cell[ElemNum].Fnum, Cell[ElemNum].Knum,keywrd, n, bnL, anL);
6172            }
6173}
6174
6175
6176/***********************************************************************
6177void add_bnL_sys_elem(const int Fnum, const int Knum, const char *keywrd,
6178                      const int n, const double bnL, const double anL)
6179                         
6180   Purpose:
6181       Add the field error with the previous value, then
6182        the summmation value replace the previous value,
6183        in the PBsys definition of multipole.   
6184   
6185   Input:
6186      Fnum           family index
6187      Knum           kids index   
6188      keywrd         "rms" or "sys"
6189                     "rms":  random  multipole error
6190                     "sys":  systematic multipole error
6191      n              order of the error
6192      bnL            absolute integrated B component for the n-th error
6193      anL            absolute integrated A component for the n-th error
6194           
6195
6196     
6197   Output:
6198      None
6199     
6200  Return:
6201      None
6202     
6203  Global variables
6204      None
6205   
6206  Specific functions:
6207     None   
6208     
6209 Comments:
6210     10/2010  Written Jianfeng Zhang
6211     
6212     Rms error on the quadrupoles: only works for full quadrupole, not for half quadrupole
6213**********************************************************************/
6214void Add_bnL_sys_elem(const int Fnum, const int Knum, const char *keywrd,
6215                      const int n, const double bnL, const double anL)
6216{
6217  elemtype  elem;
6218  double *elemMPB; //skew components of the multipole
6219 // double *elemMPBb; //right components of the multipole
6220  const bool  prt = false;
6221
6222  elem = Cell[Elem_GetPos(Fnum, Knum)].Elem;
6223 
6224   
6225   if(strcmp("sys",keywrd)==0){ 
6226
6227     elemMPB = elem.M->PBsys;
6228
6229   }
6230  if(strcmp("rms",keywrd)==0){
6231   
6232    elemMPB = elem.M->PBrms;
6233   /* save the random scale factor of rms error PBrms*/ 
6234    elem.M->PBrnd[HOMmax+n] = normranf(); 
6235    elem.M->PBrnd[HOMmax-n] = normranf(); 
6236     
6237  }
6238
6239  if (elem.PL != 0.0) {
6240 
6241    elemMPB[HOMmax+n] += bnL/elem.PL;
6242    elemMPB[HOMmax-n] += anL/elem.PL;
6243  } else {
6244 
6245    // thin kick
6246    elemMPB[HOMmax+n] += bnL; 
6247    elemMPB[HOMmax-n] += anL;
6248  }
6249 
6250  Mpole_SetPB(Fnum, Knum, n);    //set for Bn component
6251  Mpole_SetPB(Fnum, Knum, -n);   //set for An component
6252
6253  if (prt)
6254    printf("add the %s error:  n=%d component of %s, bnL = %e,  %e, anL = %e,  %e\n",
6255           keywrd,n, Cell[Elem_GetPos(Fnum, Knum)].Elem.PName,
6256           bnL, elemMPB[HOMmax+n],anL, elemMPB[HOMmax-n]);
6257}
6258
6259/***********************************************************************
6260void SetCorrQtErr_fam(char const *fic, const int Fnum, const double conv, const double r0,
6261                        const int n, const double Bn, const double An)
6262                         
6263   Purpose:
6264       Set multipole field error to the thick sextupole which also functions as
6265       skew quadrupoles, horizontal and vertical correctors which are used for
6266       orbit correction.
6267           
6268   Input:
6269      fic             file name with measured corrector value or qt values
6270      Fnum            family index of horizontal or vertical corrector or skew quadrupole
6271      conv            conversion from A to T.m for soleil
6272      r0              radius at which error is measured
6273      n               order of the error
6274      Bn              integrated B component for the n-th error
6275      An              integrated A component for the n-th error     
6276     
6277   Output:
6278      None
6279     
6280  Return:
6281      None
6282     
6283  Global variables
6284      None
6285   
6286  Specific functions:
6287     None   
6288     
6289 Comments:
6290   
6291     a.) Measured corrector value is read from a file "fic"
6292     b.) correctors are at the same location of some sextupoles,
6293         so their multipole errors are added to the thick sextupoles
6294         which also functions as these correctors. 
6295                 
6296       10/2010  Written by Jianfeng Zhang
6297**********************************************************************/
6298void AddCorrQtErr_fam(char const *fic, const int Fnum, const double conv, const char *keywrd, const double r0,
6299                        const int n, const double Bn, const double An)
6300{
6301  int     i = 0, N = 0, corr_index = 0;
6302  double  bnL = 0.0, anL = 0.0;
6303  double  brho = 0.0, conv_strength = 0.0;
6304  double  corr;   /* skew quadrupole horizontal or vertical corrector error, read from a file*/
6305  int    corrlistThick[120];   /* index of associated sextupole*/
6306 
6307  FILE  *fi;
6308 
6309 
6310 
6311  brho = globval.Energy/0.299792458; /* magnetic rigidity */
6312   
6313  // assign the design order
6314    if(Cell[Elem_GetPos(Fnum,1)].Elem.M->n_design == 2 )
6315    N = 2; /* skew quadrupole*/
6316    else
6317    N = 1; /* correctors, they act like dipoles, so N =1, but in the lattice reading, their n_design = 0!!!!*/ 
6318   
6319
6320  /* Open file with multipole errors*/
6321   if ((fi = fopen(fic,"r")) == NULL)
6322  {
6323    fprintf(stderr, "Error while opening file %s \n",fic);
6324    exit_(1);
6325  }
6326   
6327   
6328  /* find index of sextupole associated with the corrector */
6329 // solution 1: find by names
6330 // solution 2: use a predefined list
6331 // solution 3: something smart ???
6332  for (i=0; i< GetnKid(Fnum); i++){
6333    if (trace) fprintf(stdout, "%d\n", i);
6334   
6335     corr_index = Elem_GetPos(Fnum, i+1);
6336   
6337    if (Cell[corr_index-1].Elem.PName[0] == 's' && Cell[corr_index-1].Elem.PName[1] == 'x')
6338      corrlistThick[i] = corr_index-1;
6339    else{
6340   
6341      if (Cell[corr_index+1].Elem.PName[0] == 's' && Cell[corr_index+1].Elem.PName[1] == 'x')
6342        corrlistThick[i] = corr_index+1;
6343      else{
6344       
6345        if (Cell[corr_index+2].Elem.PName[0] == 's' && Cell[corr_index+2].Elem.PName[1] == 'x')
6346          corrlistThick[i] = corr_index+2;
6347        else{
6348       
6349          if (Cell[corr_index-2].Elem.PName[0] == 's' && Cell[corr_index-2].Elem.PName[1] == 'x')
6350            corrlistThick[i] = corr_index-2;
6351          else{
6352           
6353            if (Cell[corr_index+3].Elem.PName[0] == 's' && Cell[corr_index+3].Elem.PName[1] == 'x')
6354              corrlistThick[i] = corr_index+3;
6355            else{
6356             
6357              if (Cell[corr_index-3].Elem.PName[0] == 's' && Cell[corr_index-3].Elem.PName[1] == 'x')
6358                corrlistThick[i] = corr_index-3;
6359              else fprintf(stdout, "Warning: Sextupole not found associated with corrector or skew quadrupole! \n");
6360            }
6361          }
6362        }
6363      }
6364    }
6365  }
6366 
6367 
6368  // add the multipole errors to the associated sextupole
6369   for (i = 0; i < GetnKid(Fnum); i++)
6370  {
6371    fscanf(fi,"%le \n", &corr); /* read the corrector values from a file */
6372   
6373    if (r0 == 0.0) {
6374    // input is: (b_n*L), (a_n*L) ???
6375      Add_bnL_sys_elem(Cell[corrlistThick[i]].Fnum,Cell[corrlistThick[i]].Knum,keywrd, n, Bn, An);
6376    } else {
6377        conv_strength = corr*conv/brho; 
6378        // absolute integrated error field strength
6379        bnL = Bn/pow(r0, n-N)*conv_strength; 
6380        anL = An/pow(r0, n-N)*conv_strength;
6381       
6382        Add_bnL_sys_elem(Cell[corrlistThick[i]].Fnum,Cell[corrlistThick[i]].Knum,keywrd, n, bnL, anL); 
6383         
6384      }
6385    }
6386  fclose(fi); /* close corrector file */
6387}
6388
6389/****************************************************************************/
6390/* void FitTune4(long qf1,long qf2, long qd1, long qd2, double nux, double nuy)
6391
6392   Purpose:
6393       Fit tunes to the target values using quadrupoles "qf1","qf2", "qd1", and "qd2".
6394       Specific for soleil lattice, in which each quadrupole is cut into two parts
6395       in order to get the optical parameters at the center of quadrupoles.
6396   Input:
6397       qf1: tuned half quadrupole
6398       qf2: tuned another half quadrupole
6399       qd1: tuned half quadrupole
6400       qd2: tuned another half quadrupole
6401       nux: target horizontal tune
6402       nuy: target vertical tune
6403   Output:
6404       none
6405
6406   Return:
6407       none
6408
6409   Global variables:
6410     
6411   specific functions:
6412
6413   Comments:     
6414     See also:
6415          FitTune(long qf, long qd, double nux, double nuy) in physlib.cc
6416
6417****************************************************************************/
6418void FitTune4(long qf1,long qf2, long qd1, long qd2, double nux, double nuy)
6419{
6420  long      i;
6421  iVector2  nq1 = {0,0},nq2 = {0,0}, nq={0,0};
6422  Vector2   nu = {0.0, 0.0};
6423  fitvect   qfbuf, qdbuf;
6424
6425  /* Get elements for the first quadrupole family */
6426  nq1[X_] = GetnKid(qf1); // get number of elements for family qf1
6427  nq2[X_] = GetnKid(qf2); // get number of elements for family qf2
6428  for (i = 1; i <= (nq1[X_]+nq2[X_]); i++)
6429    {
6430      if(i<=nq1[X_])
6431        qfbuf[i-1] = Elem_GetPos(qf1, i);
6432      else
6433        qfbuf[i-1] = Elem_GetPos(qf2, (i-nq1[X_]));
6434    }
6435 
6436  /* Get elements for the second quadrupole family*/
6437  nq1[Y_] = GetnKid(qd1);  // get number of elements for family qd1
6438  nq2[Y_] = GetnKid(qd2);  // get number of elements for family qd2
6439  for (i = 1; i <= (nq1[Y_]+nq2[Y_]); i++)
6440    {
6441      if(i<=nq1[Y_])
6442        qdbuf[i-1] = Elem_GetPos(qd1, i);
6443      else
6444        qdbuf[i-1] = Elem_GetPos(qd2, (i-nq1[Y_]));
6445    }
6446   
6447  nu[X_] = nux; nu[Y_] = nuy;
6448  nq[X_] = nq1[X_]+nq1[X_],nq[Y_] = nq1[Y_]+nq1[Y_];
6449 
6450  /* fit tunes */
6451  Ring_Fittune(nu, nueps, nq, qfbuf, qdbuf, nudkL, nuimax);
6452}
6453
6454/**********************************************************************
6455void PrintTrack(const char *TrackFile, double x, double px, double y,double py,
6456           double delta, double ctau, long int nmax)
6457           
6458  Purpose:         
6459    Print the coordinates at each lattice element by tracking around COD
6460
6461  Input:
6462      TrackFile        file to be print
6463      x                initial x relative to closed orbit
6464      px               initial px relative to closed orbit
6465      y                initial y relative to closed orbit
6466      py               initial py relative to closed orbit
6467      delta            initial delta relative to closed orbit
6468      ctau             initial c*tau relative to closed orbit
6469      nmax             maximum number of turns
6470     
6471     
6472  Output:
6473 
6474  Comments:
6475    Written by Jianfeng Zhang  @ synchro. soleil 05/2011   
6476**********************************************************************/ 
6477void PrintTrack(const char *TrackFile, double x, double px, double y,double py, 
6478           double delta, double ctau, long int nmax)
6479{
6480   
6481    long int i,pos = 1;
6482    long int lastn = 0, lastpos = 0;
6483    Vector x0, x1, x2, xf,codvector[Cell_nLocMax];
6484    FILE *outf;
6485    struct    tm *newtime;
6486   
6487    bool prt = false;
6488           
6489    outf = file_write(TrackFile);
6490    /* Get time and date */
6491    newtime = GetTime();
6492
6493    fprintf(outf, "# Tracking using TRACY III-- %s -- %s\n",TrackFile, asctime2(newtime));
6494    fprintf(outf, "#\n"); 
6495   // fprintf(outf, "# work tunes: %7.5f %7.5f\n",globval.TotalTune[0], globval.TotalTune[1]);               
6496    fprintf(outf, "#    i  ElemName            S           x            p_x           y          p_y");
6497    fprintf(outf, "         delta         cdt     NTurns \n");
6498    fprintf(outf, "#                          [m]        [mm]         [mrad]        [mm]        [mrad]");     
6499    fprintf(outf, "        [%%]          [mm]\n");
6500
6501   
6502    //initial coordinates
6503    x0[x_] = x;
6504    x0[px_] = px;
6505    x0[y_] = y;
6506    x0[py_] = py;
6507    x0[delta_] = delta;
6508    x0[ct_] = ctau;         
6509    //get the close orbit at each element around the ring
6510    set_vectorcod(codvector, delta);                 
6511    //get the absolute initial coordinates                   
6512    x2[x_] = x0[x_] + codvector[1][x_];
6513    x2[px_] = x0[px_] + codvector[1][px_];
6514    x2[y_] = x0[y_] + codvector[1][y_];
6515    x2[py_] = x0[py_] + codvector[1][py_];
6516    if (globval.Cavity_on) {
6517        x2[delta_] = x0[delta_] + codvector[1][delta_];
6518        x2[ct_] = x0[ct_] + codvector[1][ct_];
6519    } else {
6520        x2[delta_] = x0[delta_];
6521        x2[ct_] = x0[ct_];
6522    }
6523     
6524 //print the coordinates at each elements   
6525    do {
6526        pos = 1;//track from first element
6527        (lastn)++;
6528        for (i = 0; i < nv_; i++)  //nv_ = 6
6529            x1[i] = x2[i];
6530
6531        while( pos <= globval.Cell_nLoc){ 
6532         
6533          Cell_Pass(pos, pos, x2, lastpos);             
6534          //check whether particle is lost
6535          if (!CheckAmpl(x2, pos)){
6536              fprintf(stderr,"Error!!! %d turn, Particle lost at element: %s!",
6537                              lastn, Cell[pos].Elem.PName);
6538               exit_(1);
6539          }
6540          //get the coordinates around the closed orbit   
6541          for (i = x_; i <= py_; i++)   //x_=0,px_=1,y_=2,py_=3
6542            xf[i] = x2[i] - codvector[pos][i];
6543           
6544          for (i = delta_; i <= ct_; i++) //delta_=4,ct_=5
6545            if (globval.Cavity_on && (i != ct_))
6546              xf[i] = x2[i] - codvector[pos][i];
6547            else
6548              xf[i] = x2[i];
6549           
6550          if (prt) {
6551            printf("%4ld %4ld %s %6.4f %10.4f %10.4f %10.4f %10.4f %10.4f %10.4f %4ld \n",
6552                     pos, lastpos,Cell[pos].Elem.PName,Cell[pos].S, 1e3*xf[x_], 1e3*xf[px_], 
6553                     1e3*xf[y_], 1e3*xf[py_],1e2*xf[delta_], 1e3*xf[ct_],lastn);
6554          }     
6555          fprintf(outf,"%6d  %s %8.4e %12.4e %12.4e %12.4e %12.4e %12.4e %12.4e %4ld \n",
6556                     pos,Cell[pos].Elem.PName,Cell[pos].S, 1e3*xf[x_], 1e3*xf[px_], 
6557                     1e3*xf[y_], 1e3*xf[py_],1e2*xf[delta_], 1e3*xf[ct_],lastn);           
6558       
6559        pos++;               
6560        }//finish of tracking and printing to file 
6561       
6562    } while ((lastn != nmax) && (lastpos == globval.Cell_nLoc));
6563
6564//     if (globval.MatMeth)
6565//         Cell_Pass(0, globval.Cell_nLoc, x1, lastpos);
6566
6567    fclose(outf);   
6568}
6569/*******************************************************************************************************
6570  void ReadVirtualSkewQuad(const char *SkewQuadFile)
6571 
6572  Purpose:
6573       Set sources of coupling on SOLEIL storage ring, to simulate localized skew gradient.
6574       Then calculate the coupling.
6575 
6576  Comments:
6577      Based on the tracy-2.7 file VirtualSkewQuad(void).
6578     
6579      21/12/2011  Jianfeng Zhang@soleil
6580      Fix the bug to call Elem_Getpos() in
6581      SetKLpar(ElemIndex("SQ"),i+1, mOrder=2L, corr_strength),
6582      the start kid index of the family starts from 1 !!!!!
6583     
6584*****************************************************************************************************/
6585 void ReadVirtualSkewQuad(const char *VirtualSkewQuadFile)
6586{
6587  int     nqtcorr= 0;                   /* Number of virtual skew quadrupoles */ 
6588  int     qtcorrlist[max_str];          /* virtual skew quad list */
6589  int      i=0;
6590  long     mOrder = 0L;
6591  double  qtcorr[max_str];                      /* virtual skew quad value in Amps */
6592  double  conv = 0.0, brho = 0.0, corr_strength =0.0;
6593 
6594  brho = globval.Energy/0.299792458;            /* magnetic rigidity */
6595  conv = 93.88e-4;                              /*conversion des A en T*/
6596 
6597  nqtcorr = GetnKid(ElemIndex("SQ"));
6598  printf("Number of virtual skew quadrupoles: %d\n",nqtcorr);
6599
6600  /* open virtual QT corrector file */
6601  if ((fi = fopen(VirtualSkewQuadFile,"r")) == NULL)
6602  {
6603    fprintf(stderr, "Error while opening file %s \n",VirtualSkewQuadFile);
6604    exit(1);
6605  }
6606
6607  for (i = 1; i <= nqtcorr; i++){
6608    fscanf(fi,"%le \n", &qtcorr[i-1]);
6609    corr_strength = qtcorr[i-1]*conv/brho;
6610    //corr_strength = 20.*conv/brho;
6611    SetKLpar(ElemIndex("SQ"),i, mOrder=2L, corr_strength);
6612    if(trace)
6613      printf("virtual skew quadrupole: %d, qtcorr=%le, corr_strength=%le\n",i,qtcorr[i-1],corr_strength);
6614  }
6615  fclose(fi); 
6616}
6617/*********************************************************************************
6618void CODCorrect(FILE *hcorr_file,FILE *vcorr_file,int n_orbit,int nwh,int nwv)
6619
6620  Purpose:
6621     Get the response matrix between bpms and h/v correctors; then call CorrectCODs( )
6622     to do orbit correction; finally saved the summary of the orbit correction.
6623     
6624     
6625     
6626  Comments:
6627         Written by Jianfeng Zhang@soleil   20/12/2011
6628     
6629*********************************************************************************/
6630void CODCorrect(const char *hcorr_file, const char *vcorr_file,int n_orbit,int nwh,int nwv)
6631{
6632  bool    cod = false;
6633  int     k=0;
6634  FILE    *hOrbitFile, *vOrbitFile, *OrbScanFile;
6635  int     hcorrIdx[nCOR], vcorrIdx[nCOR]; //list of corr for orbit correction
6636   
6637  //initialize the corrector list
6638  for ( k = 0; k < nCOR; k++){
6639    hcorrIdx[k] = -1;
6640    vcorrIdx[k] = -1;
6641  }
6642
6643 
6644  //Get response matrix between bpm and correctors, and then print the SVD setting to the files
6645  // select correctors to be used
6646  readCorrectorList(hcorr_file, vcorr_file, hcorrIdx, vcorrIdx);
6647   
6648  fprintf(stdout, "\n\nSVD correction setting:\n");
6649  fprintf(stdout, "H-plane %d singular values:\n", nwh);
6650  fprintf(stdout, "V-plane %d singular values:\n\n",nwv);
6651   
6652  // compute beam response matrix
6653  printf("\n");
6654  printf("Computing beam response matrix\n");
6655  //get the response matrix between bpm and correctors
6656  gcmats(globval.bpm, globval.hcorr, 1, hcorrIdx); 
6657  gcmats(globval.bpm, globval.vcorr, 2, vcorrIdx);
6658  /*    gcmat(globval.bpm, globval.hcorr, 1);
6659        gcmat(globval.bpm, globval.vcorr, 2);*/
6660   
6661  // print response matrices to files 'svdh.out' and file 'svdv.out'
6662  prt_gcmat(globval.bpm, globval.hcorr, 1);
6663  prt_gcmat(globval.bpm, globval.vcorr, 2); 
6664
6665  //print the statistics of orbit in file 'OrbScanFile.out'
6666  OrbScanFile = file_write("OrbScanFile.out"); 
6667   
6668  //write files with orbits at all element locations
6669  hOrbitFile = file_write("horbit.out");
6670  vOrbitFile = file_write("vorbit.out");
6671   
6672  fprintf(hOrbitFile, "# First line: s-location (m) \n");
6673  fprintf(hOrbitFile, "# After orbit correction:  Horizontal closed orbit at all element locations (with %3d BPMs) at different loop\n", GetnKid(globval.bpm));
6674  fprintf(vOrbitFile, "# First line s-location (m) \n");
6675  fprintf(vOrbitFile, "# After orbit correction:  Vertical closed orbit at all element locations (with %3d BPMs) at different loop\n", GetnKid(globval.bpm));
6676   
6677  for (k = 0; k < globval.Cell_nLoc; k++){
6678    fprintf(hOrbitFile, "% 9.3e  ", Cell[k].S);
6679    fprintf(vOrbitFile, "% 9.3e  ", Cell[k].S);
6680  } // end for
6681   
6682  fprintf(hOrbitFile, "\n");
6683  fprintf(vOrbitFile, "\n");   
6684     
6685 
6686  //prepare for the orbit correction   
6687  // Clear trim setpoints
6688  set_bnL_design_fam(globval.hcorr, Dip, 0.0, 0.0);
6689  set_bnL_design_fam(globval.vcorr, Dip, 0.0, 0.0);
6690
6691  // Beam based alignment
6692  if (bba) {
6693    Align_BPM2quad(Quad);
6694  }
6695 
6696  //orbit correction 
6697  cod = CorrectCODs(hOrbitFile, vOrbitFile, OrbScanFile, n_orbit, nwh, nwv, hcorrIdx, vcorrIdx); 
6698     
6699        /*      cod = CorrectCOD_N(ae_file, n_orbit, n_scale, k);*/
6700  printf("\n");
6701       
6702  if (cod){
6703        /*         printf("done with orbit correction, now do coupling",
6704               " correction plus vert. disp\n");*/
6705           
6706    printf("Orbit correction succeeded\n");
6707  }else{
6708    fprintf(stdout, "!!! Orbit correction failed\n");
6709    exit_(1);
6710    }
6711              //chk_cod(cod, "iter # %3d error_and_correction");   
6712 
6713      // for debugging
6714      //print flat lattice
6715      //sprintf(mfile_name, "flat_file.%03d.dat",k);
6716      //prtmfile(mfile_name);
6717   
6718  // close file giving orbit at BPM location
6719  fclose(hOrbitFile);
6720  fclose(vOrbitFile); 
6721  fclose(OrbScanFile);
6722}
6723
Note: See TracBrowser for help on using the repository browser.