From 4d2a906b572cd3999ca99c69a009add42fda7547 Mon Sep 17 00:00:00 2001 From: zhang <zhang@9a6e40ed-f3a0-4838-9b4a-bf418f78e88d> Date: Fri, 8 Apr 2011 16:44:01 +0000 Subject: [PATCH] 08/04/2011 Add the functions to do orbit corrections, from nsls-ii_lib_templ.h and physlib_templ.h --- tracy/tracy/src/lsoc.cc | 944 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 934 insertions(+), 10 deletions(-) diff --git a/tracy/tracy/src/lsoc.cc b/tracy/tracy/src/lsoc.cc index c97072f..b635447 100644 --- a/tracy/tracy/src/lsoc.cc +++ b/tracy/tracy/src/lsoc.cc @@ -6,31 +6,58 @@ L. Nadolski SOLEIL 2002 Link to NAFF, Radia field maps J. Bengtsson NSLS-II, BNL 2004 - + + */ +/* for add alignment errors and do COD correction */ +#include<gsl/gsl_matrix.h> //gnu math lib +#include<gsl/gsl_linalg.h> //gnu math lib +//non-global variables bool first_h = true, first_v = true; -int m, n[2]; -double *w_lsoc[2], **A_lsoc[2], **U_lsoc[2], **V_lsoc[2]; +int m; //number of bpm +int n[2];//number of correctors +double *w_lsoc[2], **A_lsoc[2],**U_lsoc[2], **V_lsoc[2]; //response matrix between bpm and correctors + + +//global values + /* parameters for orbit correction */ + const int nCOR = 250; // maximum number of correctors + const char hOrbitFileName[] = "horbit.out"; // LSN + const char vOrbitFileName[] = "vorbit.out"; //LSN + const char OrbScanFileName[] = "OrbScanFile.out"; + + FILE *OrbScanFile; + + +/**************************************************************** +void prt_gcmat(int bpm, int corr, int plane) + + Purpose: + Print the reponse matrix between bpm and correctors. + Write the response function to file svdh.out or svdv.out + +*****************************************************************/ void prt_gcmat(int bpm, int corr, int plane) { int i, j; FILE *outf = NULL; - printf("bpm = %d, corr = %d, plane = %d\n", bpm, corr, plane); + printf("bpm family number = %d, corr family number = %d, plane = %d\n", bpm, corr, plane); if (plane == 1) outf = file_write("svdh.out"); else if (plane == 2) outf = file_write("svdv.out"); else { - printf("prt_gcmat: undefined plane %d\n", plane); + printf("prt_gcmat: undefined plane %d, plane must be '1' or '2'\n", plane); exit_(1); } - fprintf(outf,"# total monitors: %d\n", m); + fprintf(outf,"# total monitors: %d\n", m); if (plane == 1) fprintf(outf,"# total horizontal correctors: %d\n", n[plane-1]); @@ -54,8 +81,8 @@ void prt_gcmat(int bpm, int corr, int plane) fprintf(outf, "#w [%d]= \n", n[plane-1]); for (j = 1; j <= n[plane-1]; j++) fprintf(outf, "% .3e ", w_lsoc[plane-1][j]); + fprintf(outf, "\n#V [%d][%d]= \n", m, n[plane-1]); - for (i = 1; i <= n[plane-1]; i++) { for (j = 1; j <= n[plane-1]; j++) fprintf(outf, "% .3e ", V_lsoc[plane-1][i][j]); @@ -66,9 +93,11 @@ void prt_gcmat(int bpm, int corr, int plane) } -void gcmat(int bpm, int corr, int plane) -{ - /* Get correlation matrix +/********************************************************************************** + void gcmat(int bpm, int corr, int plane) + + Purpose: + Get correlation matrix ----------- \/beta beta @@ -76,7 +105,10 @@ void gcmat(int bpm, int corr, int plane) A = ------------- cos(nu pi - 2 pi|nu - nu |) ij 2 sin(pi nu) i j - */ + +*********************************************************************************/ +void gcmat(int bpm, int corr, int plane) +{ bool first; int i, j; @@ -161,3 +193,895 @@ void lsoc(int niter, int bpm, int corr, int plane) } } + + + +/************************************************************** +// The following files are copied from nsls-ii_lib_templ.h + To be tested. +*************************************************************/ +/****************************************************************************** +bool CorrectCOD_Ns(FILE *hOrbitFile, FILE *vOrbitFile, const char *ae_file, const int n_orbit, + const int n, const int k, const int nwh, const int nwv, int *hcorrIdx, int *vcorrIdx) + + Purpose: + Read in the alignment error from an external file, and then correct the orbits + using SVD method. + Input: + hOrbitFile file in which horizontal orbit is saved + vOrbitFile file in which vertical orbit is saved + ae_file file from which alignment error is readed + nhw number of horizontal singular values to be taken for the correction + nwv number of vertical singular values to be taken for the correction + + Return: + bool flag cod, if true, then the orbit is corrected successfully, + if false, then the orbit is NOT corrected successfully. + + Comments: + modif LSN + Add two arguments for SVD correction + nhw and nwv number of singular values to be taken for the correction + n_orbit number of iteration for orbit correction + n number of scaling +*******************************************************************************/ +bool CorrectCOD_Ns(FILE *hOrbitFile, FILE *vOrbitFile, const char *ae_file, const int n_orbit, + const int n, const int k, const int nwh, const int nwv, int *hcorrIdx, int *vcorrIdx) +{ + bool cod = false; + + // Clear trim setpoints + set_bnL_design_fam(globval.hcorr, Dip, 0.0, 0.0); + set_bnL_design_fam(globval.vcorr, Dip, 0.0, 0.0); + + // load misalignments + LoadAlignTol(ae_file, true, 1.0, true, k); + + if (bba) { + // Beam based alignment + Align_BPM2quad(Quad); + } + + cod = CorrectCODs(hOrbitFile, vOrbitFile, n_orbit, nwh, nwv, hcorrIdx, vcorrIdx); + + return cod; +} + +/************************************************************************************ +void readCorrectorList(const char *hCorrListName, const char *vCorrListName, int *hcorrIdx, int *vcorrIdx, + int& NhcorrIdx,int& NvcorrIdx) + + Purpose: + Read the files with horizontal and vertical correctors status, then return the list with + kid number of the correctors which are used for orbit correction. + Input: + hCorrListName file with horizontal corrector index + vCorrListName file with vertical corrector index + + Output: + hcorrIdx array with the kid number of the horizontal correctors which are used for orbit correction + vcorrIdx array with the kid number of the vertical correctors which are used for orbit correction + + Comments: + Jianfeng Zhang 06/04/2011 + Add int& NhcorrIdx,int& NvcorrIdx, to return the numbers of correctors used for orbit correction +*************************************************************************************/ +void readCorrectorList(const char *hCorrListName, const char *vCorrListName, int *hcorrIdx, int *vcorrIdx) +{ + int k, status, nKid, temp; + FILE *hCorrFile, *vCorrFile; + int NhcorrIdx = 0, NvcorrIdx = 0; //number of corretors used for orbit correction + bool prt = false; + long int loc; + char line[max_str]="not_defined"; + + status = -1; temp = -1; + hCorrFile = file_read(hCorrListName); + vCorrFile = file_read(vCorrListName); + + // get number of correctors defined in lattice + nKid = GetnKid(globval.hcorr); + printf("Horizontal Correctors: Fnum %ld nKid = %d\n", globval.hcorr, nKid); + + // first line is a comment + if (fgets(line, max_str, hCorrFile) == 0) + exit(1); + + // loop over correctors + for (k = 1; k <= nKid; k++){ + + if (fgets(line, max_str, hCorrFile) == NULL) { + printf("Error in file %s\n", hCorrListName); + return; + } + sscanf(line, "%d %d", &temp, &status); + if (prt) printf("H-plane: %d (%d) stat read %d\n", temp, k, status); + + loc = Elem_GetPos(globval.hcorr, k); + if (status == 0) { + Cell[loc].Elem.M->Status = false; + } + else{ + NhcorrIdx ++; + hcorrIdx[NhcorrIdx-1] = k; + } + + } + + fclose(hCorrFile); + + // get number of correctors defined in lattice + nKid = GetnKid(globval.vcorr); + printf("Vertical Correctors: Fnum %ld nKid = %d\n", globval.vcorr, nKid); + + // first line is a comment + if (fgets(line, max_str, vCorrFile) == 0) + return; + + // loop over correctors + for (k = 1; k <= nKid; k++){ + + if (fgets(line, max_str, vCorrFile) == NULL) { + printf("Error in file %s\n", vCorrListName); + return; + } + sscanf(line, "%d %d", &temp, &status); + if (prt) printf("V-plane: %d (%d) stat read %d\n", temp, k, status); + + loc = Elem_GetPos(globval.vcorr, k); + if (status == 0) { + Cell[loc].Elem.M->Status = false; + } + else{ + NvcorrIdx ++; + vcorrIdx[NvcorrIdx-1] = k; + } + } + + fclose(vCorrFile); + +} + + +/************************************************************** + void gcmats(int bpm, int corr, int plane, int *corrIdx, int NcorrIdx) + + Purpose: + Get the response function between BPM and Correctors + Get correlation matrix + + ----------- + \/beta beta + i j + A = ------------- cos(nu pi - 2 pi|nu - nu |) + ij 2 sin(pi nu) i j + + + Input: + bpm family number of 'bpm' + corr family number of 'correctors' + plane '1' for horizontal, '2' for vertical + corrIdx list of the kid number of the correctors + NcorrIdx number of correctors used for orbit correction + + Output: + + Return: + Response function between BPM and correctors: A_lsoc + + Comments: + + **************************************************************/ +void gcmats(int bpm, int corr, int plane, int *corrIdx) +{ + bool first; + int i, j; + long int loc; + double nu, betai, betaj, nui, nuj, spiq; + + const double eps = 1e-10; + + m = GetnKid(bpm); // number of BPMs + + //n[plane-1] = GetnKid(corr); // number of correctors + n[plane-1] = 0; + + // count number of valid correctors. Not very smart ...(????????) + for (i = 0; i < nCOR; i++){ + //printf("i=%d, elem=%d\n", i, corrIdx[i]); + if (corrIdx[i] > 0) n[plane-1]++; + } + printf("gcmats: %d active correctors in %d plane\n", n[plane-1], plane); + + + if (m > mnp) { + printf("Error!!!! gcmats: max no of BPM exceeded maximum number: %d (%d)\n", m, mnp); + exit(1); + } + + if (n[plane-1] > mnp) { + printf("Error!!!! gcmats: max no of correctors exceeded maximum number: %d (%d)\n", n[plane-1], mnp); + exit(1); + } + + first = (plane == 1)? first_h : first_v; + if (first) { + if (plane == 1) + first_h = false; + else + first_v = false; + A_lsoc[plane-1] = dmatrix(1, m, 1, n[plane-1]); + U_lsoc[plane-1] = dmatrix(1, m, 1, n[plane-1]); + w_lsoc[plane-1] = dvector(1, n[plane-1]); + V_lsoc[plane-1] = dmatrix(1, n[plane-1], 1, n[plane-1]); + } + + nu = globval.TotalTune[plane-1]; spiq = sin(M_PI*nu); + + for (i = 1; i <= m; i++) { + loc = Elem_GetPos(bpm, i); + betai = Cell[loc].Beta[plane-1]; nui = Cell[loc].Nu[plane-1]; //beta function and nu at the BPM position + for (j = 1; j <= n[plane-1]; j++) { + loc = Elem_GetPos(corr, corrIdx[j-1]); + betaj = Cell[loc].Beta[plane-1]; nuj = Cell[loc].Nu[plane-1];//beta function and nu at the corrector position + A_lsoc[plane-1][i][j] = + sqrt(betai*betaj)/(2.0*spiq)*cos(nu*M_PI-fabs(2.0*M_PI*(nui-nuj)));//response function between BPM and correctors + } + } + + for (i = 1; i <= m; i++) + for (j = 1; j <= n[plane-1]; j++) + U_lsoc[plane-1][i][j] = A_lsoc[plane-1][i][j]; + +#ifndef GSL + dsvdcmp(U_lsoc[plane-1], m, n[plane-1], w_lsoc[plane-1], V_lsoc[plane-1]); +#else + size_t gsl_dm = m; + size_t gsl_dn = n[plane-1]; + + gsl_matrix *gslm_A = gsl_matrix_alloc(gsl_dm, gsl_dn); + for (size_t i = 0; i < gsl_dm; ++i) { + for (size_t j = 0; j < gsl_dn; ++j) { + gsl_matrix_set(gslm_A, i, j, U_lsoc[plane-1][i+1][j+1]); + } + } + gsl_vector *gslv_work = gsl_vector_alloc(gsl_dn); + gsl_vector *gslv_S = gsl_vector_alloc(gsl_dn); + gsl_matrix *gslm_V = gsl_matrix_alloc(gsl_dn, gsl_dn); + gsl_linalg_SV_decomp(gslm_A, gslm_V, gslv_S, gslv_work); + + for (size_t i = 0; i < gsl_dn; ++i) w_lsoc[plane-1][i+1] = gsl_vector_get(gslv_S, i); + for (size_t i = 0; i < gsl_dm; ++i) + for (size_t j = 0; j < gsl_dn; ++j) + U_lsoc[plane-1][i+1][j+1] = gsl_matrix_get(gslm_A, i, j); + for (size_t i = 0; i < gsl_dn; ++i) + for (size_t j = 0; j < gsl_dn; ++j) + V_lsoc[plane-1][i+1][j+1] = gsl_matrix_get(gslm_V, i, j); + + gsl_vector_free(gslv_work); + gsl_vector_free(gslv_S); + gsl_matrix_free(gslm_V); + gsl_matrix_free(gslm_A); + #endif + + for (j = 1; j <= n[plane-1]; j++) + if (w_lsoc[plane-1][j] < eps) { + printf("gcmats: singular beam response matrix" + " %12.3e, plane = %d, j = %d\n", + w_lsoc[plane-1][j], plane, j); + exit(0); + } +} + + +/******************************************************************************* + void LoadFieldErrs(const char *FieldErrorFile, const bool Scale_it, + const double Scale, const bool new_rnd, const int ik) + + Purpose: + Load field errors for all elements specified in input file FieldErrorFile + + Input: + FieldErrorFile file with field error + Scale_it if ture, scale the filed error + Scale scale of the field error, Scale_it must be true + new_rnd whether to generate new scale value for the rms error + ik +********************************************************************************/ +void LoadFieldErrs(const char *FieldErrorFile, const bool Scale_it, + const double Scale, const bool new_rnd, const int ik) +{ + bool rms, set_rnd = false; + char line[max_str], name[max_str], type[max_str], *prm; + int k, n, seed_val; + double Bn, An, r0; + FILE *inf; + + const bool prt = true; + + inf = file_read(FieldErrorFile); + + + while (fgets(line, max_str, inf) != NULL) { + if (strstr(line, "#") == NULL) { // if line does not strat with # + // check for whether to set new seed + sscanf(line, "%s", name); + if (strcmp("seed", name) == 0) { // if seed number + set_rnd = true; + sscanf(line, "%*s %d", &seed_val); + printf("LoadFieldErr: setting random seed to %d\n", seed_val+ik); + iniranf(seed_val+ik); + } else { // then it is an & bn definition + sscanf(line, "%*s %s %lf", type, &r0); // read reference radius + printf("\n"); + printf("%-4s %3s %7.1le\n", name, type, r0); + rms = (strcmp("rms", type) == 0)? true : false; + if (rms && !set_rnd) { + printf("LoadFieldErr: seed not defined\n"); + exit(1); + } //end if + // skip first three parameters + strtok(line, " "); // set pointer + for (k = 1; k <= 2; k++) + strtok(NULL, " "); // pointer move to nxt element + while (((prm = strtok(NULL, " ")) != NULL) && + (strcmp(prm, "\r\n") != 0)) { + sscanf(prm, "%d", &n); + prm = get_prm(); + sscanf(prm, "%lf", &Bn); + prm = get_prm(); + sscanf(prm, "%lf", &An); + if (Scale_it) { + Bn *= Scale; + An *= Scale; + } + if (prt) + printf(" %1d %9.1e %9.1e\n", n, Bn, An); + // convert to normalized multipole components + SetFieldErrors(name, rms, r0, n, Bn, An, true); + } // end while + } // end if seed + } // end if # + } // end while file + + fclose(inf); +} + + + +/***************************************************************************************** +bool CorrectCODs(FILE *hOrbitFile, FILE *vOrbitFile, int n_orbit, int nwh, int nwv, + int *hcorrIdx, int *vcorrIdx) + + Purpose: + Correct the orbit, and print the statistics of the orbit to the file 'OrbScanFile'. +// correction algorithms + +// control of orbit + + + + Input: + hOrbitFile file to be printed with the horizontal closed orbit + vOrbitFile file to be printed with the vertical closed orbit + n_orbit number of interation to do orbit correction + nwh singular number in horizontal orbit correction + nwv singular number in vertical orbit correction + hcorrIdx array with the kid number of horizontal correctors + vcorrIdx array with the kid number of vertical correctors + Output: + + Comments: + // closed orbit correction by n_orbit iterations +// modif LSN +// Add two argument for SVD correction +// nhw and nwv number of singular values to be taken for the correction +// Modif switch sextupole by 50% for iteration #1 + + + Jianfeng Zhang 08/04/2011 Modify the routine to reduce and restore + sextupole strength, to make it work in a + general way, not lattice specific. +******************************************************************************************/ +bool CorrectCODs(FILE *hOrbitFile, FILE *vOrbitFile, int n_orbit, int nwh, int nwv, int *hcorrIdx, int *vcorrIdx) +{ + bool cod; + int i,j; + long int lastpos; + Vector2 mean, sigma, max; + const double sexred = 0.5; // reduction for sextupoles strength + + cod = getcod(0.0, lastpos); + + if (cod) { + codstat(mean, sigma, max, globval.Cell_nLoc, false); // get orbit stats at all BPMs + fprintf(OrbScanFile, "\n");//print the statistics of the orbit at all BPMs to the file + fprintf(OrbScanFile,"Initial RMS orbit (BPMs): " + " x = % 7.1e mm, y = % 7.1e mm\n", + 1e3*sigma[X_], 1e3*sigma[Y_]); + fprintf(OrbScanFile,"Initial MEAN orbit (BPMs): " + " x = % 7.1e mm, y = % 7.1e mm\n", + 1e3*mean[X_], 1e3*mean[Y_]); + fprintf(OrbScanFile,"Initial MAX orbit (BPMs): " + " x = % 7.1e mm, y = % 7.1e mm\n", + 1e3*max[X_], 1e3*max[Y_]); + codstat(mean, sigma, max, globval.Cell_nLoc, true);// get orbit stats at all lattice elements + fprintf(OrbScanFile,"Initial RMS orbit (all): " + " x = % 7.1e mm, y = % 7.1e mm\n", + 1e3*sigma[X_], 1e3*sigma[Y_]); + + //orbit correction + for (i = 0; i < n_orbit; i++){ + if (i==0){ //reduce sextupole by 50% for not be too off in tune values + // because the first time the COD is realy large, so the field + // in sextupole is not linear anymore. + for(j = 0;j <= globval.Cell_nLoc; j++) + if(Cell[j].Elem.Pkind == Mpole&&Cell[j].Elem.M->n_design == Sext) + SetdKrpar(Cell[j].Fnum,Cell[j].Knum,Sext,-sexred); + } + + lsoc2s(1, globval.bpm, globval.hcorr, 1, nwh, hcorrIdx); // correct horizontal orbit + lsoc2s(1, globval.bpm, globval.vcorr, 2, nwv, hcorrIdx); // correct vertical orbit + //fprintf(stdout, "iter %d get Orbit before\n", i); + cod = getcod(0.0, lastpos); // find closed orbit + //fprintf(stdout, "iter %d get Orbit after\n", i); + + if (i==0){ //restore sexupole strengths to nominal values + for(j = 0;j <= globval.Cell_nLoc; j++) + if(Cell[j].Elem.Pkind == Mpole&&Cell[j].Elem.M->n_design == Sext) + SetdKrpar(Cell[j].Fnum,Cell[j].Knum,Sext,1./(1.-sexred)-1.); + } + if (!cod) break; + } + + if (cod) { + // get and print out corrected orbit, and return the statistics of the orbit at all lattice elements + codstats(hOrbitFile, vOrbitFile, mean, sigma, max, globval.Cell_nLoc, true); + // return COD stats at BPM location + codstat(mean, sigma, max, globval.Cell_nLoc, false); + + fprintf(OrbScanFile,"Corrected RMS orbit (BPMs): " + " x = % 7.1e mm, y = % 7.1e mm\n", + 1e3*sigma[X_], 1e3*sigma[Y_]); + fprintf(OrbScanFile,"Corrected MEAN orbit (BPMs):" + " x = % 7.1e mm, y = % 7.1e mm\n", + 1e3*mean[X_], 1e3*mean[Y_]); + fprintf(OrbScanFile,"Corrected MAX orbit (BPMs): " + " x = % 7.1e mm, y = % 7.1e mm\n", + 1e3*max[X_], 1e3*max[Y_]); + codstat(mean, sigma, max, globval.Cell_nLoc, true); + fprintf(OrbScanFile,"Corrected RMS orbit (all): " + " x = % 7.1e mm, y = % 7.1e mm\n", + 1e3*sigma[X_], 1e3*sigma[Y_]); + // get stats for correctors + corstat(mean, sigma, max, globval.Cell_nLoc); + fprintf(OrbScanFile,"Corrected RMS CM: " + " x = % 7.1e mrad, y = % 7.1e mrad\n", + 1e3*sigma[X_], 1e3*sigma[Y_]); + fprintf(OrbScanFile,"Corrected MEAN CM: " + " x = % 7.1e mrad, y = % 7.1e mrad\n", + 1e3*mean[X_], 1e3*mean[Y_]); + fprintf(OrbScanFile,"Corrected MAX CM: " + " x = % 7.1e mrad, y = % 7.1e mrad\n", + 1e3*max[X_], 1e3*max[Y_]); + } + + fflush(OrbScanFile); + } + + return cod; +} + +/**************************************************************** +void lsoc2(int niter, int bpm, int corr, int plane, int nval) + + Purpose: + add argument nval number of singular values to be taken + +*****************************************************************/ +void lsoc2(int niter, int bpm, int corr, int plane, int nval) +// add argument nval number of singular values to be taken +{ + long int k; + svdarray b, x; + + for (int i = 1; i <= niter; i++) { + for (int j = 1; j <= m; j++) { + k = Elem_GetPos(bpm, j); + b[j] = -Cell[k].BeamPos[(plane-1)*2] + Cell[k].dS[plane-1]; + } + + #ifndef GSL + dsvbksb(U_lsoc[plane-1], w_lsoc[plane-1], V_lsoc[plane-1], + m, n[plane-1], b, x); + #else + #define gsl_dm m + #define gsl_dn n[plane-1] + gsl_matrix *gslm_A = gsl_matrix_alloc(gsl_dm, gsl_dn); + gsl_vector *gslv_work = gsl_vector_alloc(gsl_dn); + gsl_vector *gslv_S = gsl_vector_alloc(gsl_dn); + gsl_matrix *gslm_V = gsl_matrix_alloc(gsl_dn, gsl_dn); + gsl_vector *gslv_b = gsl_vector_alloc(gsl_dm); + + gsl_vector *gslv_x = gsl_vector_alloc(gsl_dn); + + for (int j = 0; j < gsl_dm; ++j) { + gsl_vector_set(gslv_b, j, b[j+1]); + } + + if (nval > gsl_dn || nval <1){ + fprintf(stdout, "Warning nval %d larger than gsl_dn %d\n", nval, gsl_dn); + nval = gsl_dn; + } + + for (int j = 0; j < gsl_dn; ++j) { + + // select number of singular values + if (j < nval) + gsl_vector_set(gslv_S, j, w_lsoc[plane-1][j+1]); + else + gsl_vector_set(gslv_S, j, w_lsoc[plane-1][j+1]*0); + + for (int i = 0; i < gsl_dm; ++i) { + gsl_matrix_set(gslm_A, i, j, U_lsoc[plane-1][i+1][j+1]); + } + for (int i = 0; i < gsl_dn; ++i) + gsl_matrix_set(gslm_V, i, j, V_lsoc[plane-1][i+1][j+1]); + } + + + + + gsl_linalg_SV_solve(gslm_A, gslm_V, gslv_S, gslv_b, gslv_x); + + for (int i = 0; i < gsl_dn; ++i) + x[i+1] = gsl_vector_get(gslv_x, i); + + gsl_vector_free(gslv_work); + gsl_vector_free(gslv_S); + gsl_vector_free(gslv_b); + gsl_vector_free(gslv_x); + gsl_matrix_free(gslm_V); + gsl_matrix_free(gslm_A); + #undef gsl_dm + #undef gsl_dn + #endif + + for (int j = 1; j <= n[plane-1]; j++) + if (plane == 1) + SetdKpar(corr, j, Dip, -x[j]); + else + SetdKpar(corr, j, -Dip, x[j]); + } +} + +/**************************************************************************** + void lsoc2s(int niter, int bpm, int corr, int plane, int nval, int *corIdx) + + Purpose: + Orbit correction. + + add argument nval number of singular values to be taken + add array of index of correctors to use + + Input: + niter interation time to do orbit correction + bpm family number of bpm + corr family number of correctors + plane '1', horizontal plane; '2',vertical plane. + nval singular number to do orbit correction + corIdx array with corrector kid number +*****************************************************************************/ +void lsoc2s(int niter, int bpm, int corr, int plane, int nval, int *corIdx) +// add argument nval number of singular values to be taken +// add array of index of correctors to use +{ + long int k; + svdarray b, x; + + for (int i = 1; i <= niter; i++) { + for (int j = 1; j <= m; j++) { + k = Elem_GetPos(bpm, j); + b[j] = -Cell[k].BeamPos[(plane-1)*2] + Cell[k].dS[plane-1];//add the displacement error of bpm + } + + #ifndef GSL + dsvbksb(U_lsoc[plane-1], w_lsoc[plane-1], V_lsoc[plane-1], + m, n[plane-1], b, x); + #else + #define gsl_dm m + #define gsl_dn n[plane-1] + gsl_matrix *gslm_A = gsl_matrix_alloc(gsl_dm, gsl_dn); + gsl_vector *gslv_work = gsl_vector_alloc(gsl_dn); + gsl_vector *gslv_S = gsl_vector_alloc(gsl_dn); + gsl_matrix *gslm_V = gsl_matrix_alloc(gsl_dn, gsl_dn); + gsl_vector *gslv_b = gsl_vector_alloc(gsl_dm); + + gsl_vector *gslv_x = gsl_vector_alloc(gsl_dn); + + for (int j = 0; j < gsl_dm; ++j) { + gsl_vector_set(gslv_b, j, b[j+1]); + } + + if (nval > gsl_dn || nval <1){ + fprintf(stdout, "Warning nval %d larger than gsl_dn %d\n", nval, gsl_dn); + nval = gsl_dn; + } + + for (int j = 0; j < gsl_dn; ++j) { + + // select number of singular values + if (j < nval) + gsl_vector_set(gslv_S, j, w_lsoc[plane-1][j+1]); + else + gsl_vector_set(gslv_S, j, w_lsoc[plane-1][j+1]*0); + + for (int i = 0; i < gsl_dm; ++i) { + gsl_matrix_set(gslm_A, i, j, U_lsoc[plane-1][i+1][j+1]); + } + for (int i = 0; i < gsl_dn; ++i) + gsl_matrix_set(gslm_V, i, j, V_lsoc[plane-1][i+1][j+1]); + } + + gsl_linalg_SV_solve(gslm_A, gslm_V, gslv_S, gslv_b, gslv_x); + + for (int i = 0; i < gsl_dn; ++i) + x[i+1] = gsl_vector_get(gslv_x, i); //get the value of correctors + + //free memory + gsl_vector_free(gslv_work); + gsl_vector_free(gslv_S); + gsl_vector_free(gslv_b); + gsl_vector_free(gslv_x); + gsl_matrix_free(gslm_V); + gsl_matrix_free(gslm_A); + #undef gsl_dm + #undef gsl_dn + #endif + + // set correctors to computed values + for (int j = 1; j <= n[plane-1]; j++) + if (plane == 1) + SetdKpar(corr, corIdx[j-1], Dip, -x[j]); + else + SetdKpar(corr, corIdx[j-1], -Dip, x[j]); + } +} + +/************************************************************** +void Align_BPM2quad(const int n) + + Purpose: + Align BPMs to adjacent multipoles. + +***************************************************************/ +void Align_BPM2quad(const int n) +{ + + + bool prt = false; + int j; + long int loc = -1, locUSQUAD = -1, locDSQUAD = -1, locQUAD = -1; + + double USQUADPosition = -1.0; + double DSQUADPosition = -1.0; + double BPM2USQUAD = 0.0; + double BPM2DSQUAD = 0.0; + + const int n_step = 10; // number of step for the search loop + + printf("\n"); + for (int i = 1; i <= GetnKid(globval.bpm); i++) { + loc = Elem_GetPos(globval.bpm, i); + + if ((loc == 1) || (loc == globval.Cell_nLoc)) { + printf("Align_BPMs: BPM at entrance or exit of lattice: %ld\n", loc); + exit(1); + } + + if (prt) printf("BPM no %1d (%8.3f)\n", i, DSQUADPosition); + + // look for adjacent downstream quadrupole + j = 1; DSQUADPosition = -1.0; + do { + if ((Cell[loc+j].Elem.Pkind == Mpole) && + (Cell[loc+j].Elem.M->n_design == n)) { + locDSQUAD = loc+j; + DSQUADPosition = Cell[locDSQUAD].S - 0.5*Cell[locDSQUAD].Elem.PL ; // BPM to Quad center + BPM2DSQUAD = fabs(DSQUADPosition - Cell[loc].S); + if (prt) printf("downstream quadrupole %s (%4.3f m)\n", Cell[locDSQUAD].Elem.PName, BPM2DSQUAD); + break; + } + j++; + } while ((j <= n_step) && ((loc + j) <= globval.Cell_nLoc)); + + // look for upstream quadrupole + j = 1; USQUADPosition = -1.0; + do { + if ((Cell[loc-j].Elem.Pkind == Mpole) && + (Cell[loc-j].Elem.M->n_design == n)) { + locUSQUAD = loc-j; + USQUADPosition = Cell[loc-j].S - 0.5*Cell[loc-j].Elem.PL; // BPM to Quad center + BPM2USQUAD = fabs(USQUADPosition - Cell[loc].S); + if (prt) printf("upstream quadrupole %s (%4.3f m) \n", Cell[locUSQUAD].Elem.PName, -BPM2USQUAD); + break; + } + j++; + } while ((j <= n_step) && ((loc - j) > 0)); + + // is up and dow stream quad found + if ((USQUADPosition != -1.0) && (DSQUADPosition != -1.0)) + { // both up and down stream quads + if (BPM2USQUAD > BPM2DSQUAD){ + locQUAD = locDSQUAD;} + else{ + locQUAD = locUSQUAD;} + }else if (USQUADPosition == -1.0){ // just downstream quad + locQUAD = locDSQUAD;} + else if (DSQUADPosition == -1.0){ // just upstream quad + locQUAD = locUSQUAD;} + + // if Quad found, set BPM error to quadrupole errors + if ((DSQUADPosition != -1.0) || (USQUADPosition != -1.0)){ + for (int k = 0; k <= 1; k++) + Cell[loc].Elem.M->PdSsys[k] = Cell[locQUAD].dS[k]; + Mpole_SetdS(globval.bpm, i); + if (prt) printf("BPM no %1d is aligned to quadrupole %s\n", i, Cell[locQUAD].Elem.PName); + } + else + printf("Align_BPMs: no multipole adjacent to BPM no %d\n", i); + } +} + + +/********************************************************************************* + The following functions are copied from physlib_templ.h, need to be tested +**********************************************************************************/ + +/*************************************************************************** +void codstats(FILE *hOrbitFile, FILE *vOrbitFile, double *mean, + double *sigma, double *xmax, long lastpos, bool all) + +Purpose: + Routines for closed orbit correction + return the mean orbit, rms orbit and maximum orbit, based on the orbits at + all lattice elements or all bpm postion, + and print the COD at all lattice elements or all bpm position to the files + 'horbit.out','vorbit.out' + + Input: + hOrbitFile name of file to be printed with cod + vOrbitFile name of file to be printed with cod + mean mean value of the orbit, horizontal or vertical + sigma rms value of the orbit, horizontal or vertical + xmax maximum value of the orbit, horizontal or vertical + lastpos last element index in the lattice + all true, then do statistics on the orbit at all elements + false, ...............................at all bpm + +***************************************************************************/ +void codstats(FILE *hOrbitFile, FILE *vOrbitFile, double *mean, double *sigma, double *xmax, long lastpos, bool all) +{ + long i = 0L, j = 0L, n = 0L; + Vector2 sum, sum2; + double codvec[2][Elem_nFamMax]; + double TEMP; + long nprint = 0L; + + //initialize + for (j = 0; j <= 1; j++) { + sum[j] = 0.0; sum2[j] = 0.0; xmax[j] = 0.0; + } + //initialize + for (j = 0; j <= 1; j++) { + for (i = 0; i <= Elem_nFamMax; i++) { + codvec[j][i] = 0.0; + } // for i + } // for j + + //start loop at 1 since in Cell_Pass element 0 is skipped (element 0 is alaways marker) + // data in index 0 is garbage + for (i = 1; i <= lastpos; i++) { + if (all || Cell[i].Fnum == globval.bpm) { + n++; + for (j = 1; j <= 2; j++) { + TEMP = Cell[i].BeamPos[j * 2 - 2]; + codvec[j-1][n-1] = TEMP; +// if display changed for BPM +/* if (Cell[i].Fnum == globval.bpm) { // got a BPM + codvec[j-1][n-1] -= Cell[i].Elem.M->PdSsys[j-1]; + }*/ + sum[j - 1] += TEMP; + sum2[j - 1] += TEMP * TEMP; + xmax[j - 1] = max(xmax[j - 1], TEMP); + } // for j + } // if loop + } // for i + + // save number of useful data + nprint = n; + + for (j = 0; j <= 1; j++) { + if (n != 0) + mean[j] = sum[j] / n; + else + mean[j] = 0.0; + if (n != 0 && n != 1) { + TEMP = sum[j]; + sigma[j] = (n * sum2[j] - TEMP * TEMP) / (n * (n - 1.0)); + } else + sigma[j] = 0.0; + if (sigma[j] >= 0.0) + sigma[j] = sqrt(sigma[j]); + else + sigma[j] = 0.0; + } + +// store data in orbit files +// two loops for speed efficiency ? + for (i = 0; i < nprint; i++) { + fprintf(hOrbitFile, "% 9.3e ", codvec[X_][i]); + } // for i + fprintf(hOrbitFile, "\n"); + fflush(hOrbitFile); + + + + for (i = 0; i < nprint; i++) { + fprintf(vOrbitFile, "% 9.3e ", codvec[Y_][i]); + } // for i + fprintf(vOrbitFile, "\n"); + fflush(vOrbitFile); +} + +/*************************************************************************** + void corstat(double *mean, double *sigma, double *xmax, long lastpos) + + Purpose: + Compute RMS, mean, max values for correctors +***************************************************************************/ + +void corstat(double *mean, double *sigma, double *xmax, long lastpos) +{ + long i, j, n[2]; + Vector2 sum, sum2; + double TEMP; + + for (j = 0; j <= 1; j++) { + sum[j] = 0.0; sum2[j] = 0.0; xmax[j] = 0.0; n[j] = 0; + } + + for (i = 0; i <= lastpos; i++) { + if (Cell[i].Fnum == globval.hcorr) { + j = 1; + n[j-1]++; + TEMP = Elem_GetKval(globval.hcorr, n[j-1], (long) Dip); + sum[j - 1] += TEMP; + sum2[j - 1] += TEMP * TEMP; + xmax[j - 1] = max(xmax[j - 1], fabs(TEMP)); + } else if (Cell[i].Fnum == globval.vcorr) { + j = 2; + n[j-1]++; + TEMP = Elem_GetKval(globval.vcorr, n[j-1], (long) (-Dip)); + sum[j - 1] += TEMP; + sum2[j - 1] += TEMP * TEMP; + xmax[j - 1] = max(xmax[j - 1], fabs(TEMP)); + } + } + + for (j = 0; j <= 1; j++) { + if (n[j] != 0) + mean[j] = sum[j] / n[j]; + else + mean[j] = 0.0; + if (n[j] != 0 && n[j] != 1) { + TEMP = sum[j]; + sigma[j] = (n[j] * sum2[j] - TEMP * TEMP) / (n[j] * (n[j] - 1.0)); + } else + sigma[j] = 0.0; + if (sigma[j] >= 0.0) + sigma[j] = sqrt(sigma[j]); + else + sigma[j] = 0.0; + } +} -- GitLab