source: TRACY3/trunk/tracy/tracy/src/soleillib.cc @ 11

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