CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_1/src/MagneticField/ParametrizedEngine/plugins/rz_harm_poly.cc

Go to the documentation of this file.
00001 #include <typeinfo>
00002 #include "rz_harm_poly.h"
00003 #include <cstdlib>
00004 
00005 using namespace magfieldparam;
00006 
00008 //                                                                             //
00009 //  Harmonic homogeneous polynomials in cylindrical system.                    //
00010 //                                                                             //
00012 
00013 //_______________________________________________________________________________
00014 unsigned rz_harm_poly::Cnt    = 0;      //Number of the "rz_harm_poly" objects
00015 double   rz_harm_poly::phival = -11111.;//Last phi value used
00016 bool     rz_harm_poly::phi_set = false; //TRUE if phi value is set
00017 unsigned rz_harm_poly::MaxM   = 0;      //Max. M among "rz_harm_poly" objects
00018 
00019 unsigned   rz_harm_poly::TASize  = 0;   //TrigArr size
00020 trig_pair *rz_harm_poly::TrigArr = 0;   //Array with angular data
00021 
00022 //_______________________________________________________________________________
00023 rz_harm_poly::rz_harm_poly(const unsigned N)
00024 {
00025 //Constructor for rz_harm_poly of length N. The polynomial P(r,z) is normalized
00026 //in such a way that dP/dz(r=0,z)=z^(N-1)
00027 //
00028    unsigned nz = N, nr = 0, nv = 0;
00029    poly2d_term v3(1./N, nr, nz);
00030 
00031    data = std::vector<poly2d_term>((N + 2) / 2, v3);
00032 
00033    while (nz >= 2) {
00034       nz -= 2;
00035       nr += 2;
00036       nv += 1;
00037       data[nv].coeff = -data[nv-1].coeff*(nz+1)*(nz+2)/(nr*nr);
00038       data[nv].np[0] = nr;
00039       data[nv].np[1] = nz;
00040    }
00041    max_pwr = N;
00042    if (max_pwr > NPwr) {
00043       NPwr = max_pwr;
00044       rz_set = false;
00045       phi_set = false;
00046    }
00047    L = N;
00048    M = 0;
00049    poly2d_base_set.insert(this);
00050    ++Cnt;
00051 }
00052 
00053 //_______________________________________________________________________________
00054 rz_harm_poly::~rz_harm_poly()
00055 {
00056    if (--Cnt) {
00057      if (std::abs(M) >= int(MaxM)) { //a number of objects still left
00058          M = 0;
00059          MaxM = GetMaxM();
00060       }
00061    } else { //last instance -> memory cleanup
00062       if (TrigArr) delete [] TrigArr;
00063       TrigArr = 0;
00064       TASize = 0;
00065       MaxM = 0;
00066       phival = -11111.;
00067       phi_set = false;
00068    }
00069 }
00070 
00071 //_______________________________________________________________________________
00072 int rz_harm_poly::GetMaxM()
00073 {
00074 //Return max abs(M) for all rz_harm_poly objects created
00075 //
00076    int M_cur, M_max = 0;
00077    std::set<poly2d_base*>::iterator it;
00078    for (it = poly2d_base_set.begin(); it != poly2d_base_set.end(); ++it) {
00079       if (typeid(**it) == typeid(rz_harm_poly)) {
00080          M_cur = std::abs(((rz_harm_poly*)(*it))->M);
00081          if (M_cur > M_max) M_max = M_cur;
00082       }
00083    }
00084    return M_max;
00085 }
00086 
00087 //_______________________________________________________________________________
00088 void rz_harm_poly::SetPhi(const double phi)
00089 {
00090 //Set value of the angle argument, adjust the TrigArr size if neccessary
00091 //and fill TrigArr if the phi value is changed
00092 //
00093    if (MaxM >= TASize) { SetTrigArrSize(MaxM+1); FillTrigArr(phi);}
00094    else if (phi != phival) FillTrigArr(phi);
00095    phival = phi;
00096    phi_set = true;
00097 }
00098 
00099 //_______________________________________________________________________________
00100 void rz_harm_poly::SetTrigArrSize(const unsigned N)
00101 {
00102 //Increase TrigArr size if neccessary
00103 //
00104    if (N <= TASize) return;
00105    if (TrigArr) delete [] TrigArr;
00106    TrigArr = new trig_pair [N];
00107    (*TrigArr) = trig_pair(1., 0.);
00108    TASize = N;
00109    phi_set = false;
00110 }
00111 
00112 //_______________________________________________________________________________
00113 void rz_harm_poly::FillTrigArr(const double phi)
00114 {
00115 //Fill TrigArr with trig_pair(jp*phi)
00116    if (!TrigArr) return;
00117    trig_pair tp(phi);
00118    TrigArr[1] = tp;
00119    for (unsigned jp = 2; jp <= MaxM; ++jp) TrigArr[jp] = TrigArr[jp-1].Add(tp);
00120 }
00121 
00122 //_______________________________________________________________________________
00123 void rz_harm_poly::PrintTrigArr(std::ostream &out, const std::streamsize prec)
00124 {
00125    out << "TrigArr: TASize = " << TASize
00126        << "\tMaxM = " << MaxM << std::endl;
00127    if (TrigArr) {
00128       if (MaxM < TASize) {
00129          unsigned jm;
00130          std::streamsize old_prec = out.precision(), wdt = prec+7;
00131          out.precision(prec);
00132          out << "M:     ";
00133          for (jm = 0; jm <= MaxM; ++jm) {
00134             out << std::setw(wdt) << std::left << jm;
00135          }
00136          out << "|\nCos_M: ";
00137          for (jm = 0; jm <= MaxM; ++jm) {
00138             out << std::setw(wdt) << std::left << TrigArr[jm].CosPhi;
00139          }
00140          out << "|\nSin_M: ";
00141          for (jm = 0; jm <= MaxM; ++jm) {
00142             out << std::setw(wdt) << std::left << TrigArr[jm].SinPhi;
00143          }
00144          out << "|" << std::endl;
00145          out.precision(old_prec);
00146       } else {
00147          out << "\tTrigArr size is not adjusted." << std::endl;
00148       }
00149    } else {
00150       out << "\tTrigArr is not allocated." << std::endl;
00151    }
00152 }
00153 
00154 //_______________________________________________________________________________
00155 rz_harm_poly rz_harm_poly::LadderUp()
00156 {
00157 //Return a polynomial with increased M
00158 //
00159    rz_harm_poly p_out; p_out.data.reserve(2*L);
00160    unsigned it;
00161    poly2d_term term;
00162 
00163    //In 2 passes (for-cycles) to get terms in z-descending order
00164    for(it = 0; it < data.size(); ++it) {
00165       term = data[it];
00166       if (term.np[0]) {
00167          term.coeff *= int(term.np[0]) - M;
00168          --term.np[0];
00169          ++term.np[1];
00170          p_out.data.push_back(term);
00171       }
00172    }
00173    for(it = 0; it < data.size(); ++it) {
00174       term = data[it];
00175       if (term.np[1]) {
00176          term.coeff *= -(int)term.np[1];
00177          --term.np[1];
00178          ++term.np[0];
00179          p_out.data.push_back(term);
00180       }
00181    }
00182    p_out.Collect();
00183    if (p_out.data.size()) {
00184       p_out.L = L;
00185       p_out.M = M+1;
00186       if (std::abs(p_out.M) > int(MaxM)) MaxM = std::abs(p_out.M);
00187       p_out.Scale(1./sqrt(double((L-M)*(L+M+1))));
00188    }
00189    return p_out;
00190 }
00191 
00192 //_______________________________________________________________________________
00193 rz_harm_poly rz_harm_poly::LadderDwn()
00194 {
00195 //Return a polynomial with decreased M
00196 //
00197    rz_harm_poly p_out; p_out.data.reserve(2*L);
00198    unsigned it;
00199    poly2d_term term;
00200 
00201    //In 2 passes (for-cycles) to get terms in z-descending order
00202    for(it = 0; it < data.size(); ++it) {
00203       term = data[it];
00204       if (term.np[0]) {
00205          term.coeff *= -int(term.np[0]) - M;
00206          --term.np[0];
00207          ++term.np[1];
00208          p_out.data.push_back(term);
00209       }
00210    }
00211    for(it = 0; it < data.size(); ++it) {
00212       term = data[it];
00213       if (term.np[1]) {
00214          term.coeff *= term.np[1];
00215          --term.np[1];
00216          ++term.np[0];
00217          p_out.data.push_back(term);
00218       }
00219    }
00220    p_out.Collect();
00221    if (p_out.data.size()) {
00222       p_out.L = L;
00223       p_out.M = M-1;
00224       if (std::abs(p_out.M) > int(MaxM)) MaxM = std::abs(p_out.M);
00225       p_out.Scale(1./sqrt(double((L+M)*(L-M+1))));
00226    }
00227    return p_out;
00228 }
00229