CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_14/src/MagneticField/ParametrizedEngine/plugins/rz_poly.cc

Go to the documentation of this file.
00001 #include <iostream>
00002 #include "rz_poly.h"
00003 
00004 using namespace std;
00005 using namespace magfieldparam;
00006 
00007 //_______________________________________________________________________________
00008 rz_poly::rz_poly(int N)
00009 {
00010    int nz, nr = 0, nv, nt;
00011    poly_term  v3;
00012    
00013    if (N < 2) N = 2;
00014    data.reserve(N);
00015 
00016    v3.coeff = 1.;
00017    v3.np[0] = 0;
00018    v3.np[1] = 1;
00019    
00020    data.push_back(poly_vect(1, v3));
00021    
00022    for (int m = 2; m <=N; ++m) {
00023       nz = m;
00024       nr = 0;
00025       nv = 0;
00026       v3.coeff = 1./m;
00027       v3.np[0] = nr;
00028       v3.np[1] = nz;
00029 
00030       nt = (m + 2) / 2;
00031       poly_vect v3x(nt, v3);
00032       
00033       while (nz >= 2) {
00034          nz -= 2;
00035          nr += 2;
00036          nv += 1;
00037          v3x[nv].coeff = -v3x[nv-1].coeff*(nz+1)*(nz+2)/(nr*nr);
00038          v3x[nv].np[0] = nr;
00039          v3x[nv].np[1] = nz;
00040       }
00041       data.push_back(v3x);
00042    }
00043    max_nr = nr+1;
00044    max_nz = N +1;
00045    r_pow = new double [max_nr];
00046    z_pow = new double [max_nz];
00047    fill(r_pow, r_pow+max_nr, 1.);
00048    fill(z_pow, z_pow+max_nz, 1.);
00049    
00050    n_active = data.size();
00051    is_off = new bool [n_active];
00052    fill(is_off, is_off+n_active, false);
00053 }
00054 
00055 //_______________________________________________________________________________
00056 rz_poly::rz_poly(const rz_poly& S)
00057 {
00058    data = S.data;
00059    max_nr = S.max_nr;
00060    max_nz = S.max_nz;
00061    n_active = S.n_active;
00062 
00063    if (max_nr) {
00064       r_pow = new double [max_nr];
00065       copy(S.r_pow, S.r_pow+max_nr, r_pow);
00066    } else r_pow = 0;
00067 
00068    if (max_nz) {
00069       z_pow = new double [max_nz];
00070       copy(S.z_pow, S.z_pow+max_nz, z_pow);
00071    } else z_pow = 0;
00072 
00073    if (S.is_off) {
00074       is_off = new bool [data.size()];
00075       copy(S.is_off, S.is_off+data.size(), is_off);
00076    } else is_off = 0;
00077 }
00078 
00079 //_______________________________________________________________________________
00080 rz_poly::~rz_poly()
00081 {
00082    if (is_off) delete [] is_off;
00083    if (r_pow)  delete [] r_pow;
00084    if (z_pow)  delete [] z_pow;
00085 }
00086 
00087 //_______________________________________________________________________________
00088 void rz_poly::SetOFF(int npoly)
00089 {
00090    if ((npoly < 0) || (npoly >= (int)data.size())) return;
00091    if (is_off[npoly]) return;
00092    is_off[npoly] = true;
00093    --n_active;
00094 }
00095 
00096 //_______________________________________________________________________________
00097 void rz_poly::SetON(int npoly)
00098 {
00099    if ((npoly < 0) || (npoly >= (int)data.size())) return;
00100    if (is_off[npoly]) {
00101       is_off[npoly] = false;
00102       ++n_active;
00103    }
00104 }
00105 
00106 //_______________________________________________________________________________
00107 void rz_poly::Print()
00108 {
00109    if (!data.size()) {
00110       cout << "The \"rz_poly\" object is NOT initialized!" << endl;
00111       return;
00112    }
00113    
00114    for (unsigned int ip = 0; ip < data.size(); ++ip) {
00115       cout << "Polynomial " << ip << " (size=" << data[ip].size() << ", status=";
00116       if (is_off[ip]) cout << "OFF):" << endl;
00117       else            cout << "ON):"  << endl;
00118       for (unsigned int it = 0; it < data[ip].size(); ++it) {
00119          cout << "\tnr="    << data[ip][it].np[0]
00120               << "\tnz="    << data[ip][it].np[1]
00121               << "\tcoeff=" << data[ip][it].coeff
00122               << endl;
00123       }
00124    }
00125 }
00126 
00127 //_______________________________________________________________________________
00128 rz_poly rz_poly::Diff(int nvar, bool keep_empty)
00129 {
00130 //Return the derivative of original polynomial by variable nvar. 
00131 //If keep_empty=true, resulting polynomial may contain zero basis terms,
00132 //otherwise the resulting polynomial will be compressed, so that corresponding
00133 //basis terms will be shifted relatively to the original polynomial.
00134 //
00135    poly_term  v3;
00136    rz_poly p_out;
00137    p_out.data.reserve(data.size());
00138    
00139    bool *tmp_mask = new bool [data.size()];
00140    unsigned int  ind_tmp = 0;
00141    int   tmp_act = 0;
00142    
00143    for (unsigned int ip = 0; ip < data.size(); ++ip) {
00144       poly_vect v3x;
00145       v3x.reserve(data[ip].size());
00146       for (unsigned int it = 0; it < data[ip].size(); ++it) {
00147          v3 = data[ip][it];
00148          v3.coeff = data[ip][it].coeff * data[ip][it].np[nvar];
00149          if (v3.coeff != 0) {
00150             v3.np[nvar] = data[ip][it].np[nvar] - 1;
00151             v3x.push_back(v3);
00152          }
00153       }
00154       if (v3x.size() || keep_empty) {
00155          v3x.resize(v3x.size());
00156          p_out.data.push_back(v3x);
00157          tmp_mask[ind_tmp] = is_off[ip];
00158          ++ind_tmp;
00159          if (! is_off[ip]) ++tmp_act;
00160       }
00161    }
00162    
00163    p_out.data.resize(p_out.data.size());
00164    p_out.max_nr = max_nr;
00165    p_out.max_nz = max_nz;
00166 
00167    if (nvar == 0) --p_out.max_nr; else --p_out.max_nz;
00168    
00169    p_out.r_pow = new double [p_out.max_nr];
00170    copy(r_pow, r_pow+p_out.max_nr, p_out.r_pow);
00171    p_out.z_pow = new double [p_out.max_nz];
00172    copy(z_pow, z_pow+p_out.max_nz, p_out.z_pow);
00173    
00174    p_out.n_active = tmp_act;
00175    p_out.is_off = new bool [p_out.data.size()];
00176    copy(tmp_mask, tmp_mask+p_out.data.size(), p_out.is_off);
00177    
00178    delete [] tmp_mask;
00179 
00180    return p_out;
00181 }
00182 
00183 //_______________________________________________________________________________
00184 rz_poly rz_poly::Int(int nvar)
00185 {
00186 //Return the integral of original polynomial by variable nvar
00187 //
00188    rz_poly p_out;
00189    p_out.data = data;
00190    for (unsigned int ip = 0; ip < data.size(); ++ip) {
00191       for (unsigned int it = 0; it < data[ip].size(); ++it) {
00192          p_out.data[ip][it].coeff /= ++p_out.data[ip][it].np[nvar];
00193       }
00194    }
00195    
00196    p_out.max_nr = max_nr;
00197    p_out.max_nz = max_nz;
00198 
00199    if (nvar == 0) ++p_out.max_nr; else ++p_out.max_nz;
00200    
00201    p_out.r_pow = new double [p_out.max_nr];
00202    copy(r_pow, r_pow+max_nr, p_out.r_pow);
00203    p_out.z_pow = new double [p_out.max_nz];
00204    copy(z_pow, z_pow+max_nz, p_out.z_pow);
00205    
00206    if (nvar == 0) p_out.r_pow[max_nr] = p_out.r_pow[max_nr-1] * r_pow[1];
00207    else           p_out.z_pow[max_nz] = p_out.z_pow[max_nz-1] * z_pow[1];
00208 
00209    p_out.n_active = n_active;
00210    p_out.is_off = new bool [data.size()];
00211    copy(is_off, is_off+data.size(), p_out.is_off);
00212    
00213    return p_out;
00214 }
00215 
00216 //_______________________________________________________________________________
00217 rz_poly& rz_poly::operator*=(double C)
00218 {
00219 //Multiply the polynomial by a constant. Skips terms that are switched off
00220 
00221    for (unsigned int ip = 0; ip < data.size(); ++ip) {
00222       if (is_off[ip]) continue;
00223       for (unsigned int it = 0; it < data[ip].size(); ++it) {
00224          data[ip][it].coeff *= C;
00225       }
00226    }
00227    return *this;
00228 }
00229 
00230 //_______________________________________________________________________________
00231 rz_poly& rz_poly::operator*=(double *C)
00232 {
00233 //Multiply the polynomial by an array. Skips terms that are switched off
00234 
00235    for (unsigned int ip = 0; ip < data.size(); ++ip) {
00236       if (is_off[ip]) continue;
00237       for (unsigned int it = 0; it < data[ip].size(); ++it) {
00238          data[ip][it].coeff *= *C;
00239       }
00240       ++C;
00241    }
00242    return *this;
00243 }
00244 
00245 //_______________________________________________________________________________
00246 double rz_poly::GetSVal(double r, double z, double *C)
00247 {
00248 //Return value of a polynomial, ignoring terms, that are switched off
00249 
00250    if (r_pow == 0) return 0.;
00251    
00252    double term, rez = 0.;
00253    int ip, it;
00254    
00255    if (r != r_pow[1]) for (ip = 1; ip < max_nr; ++ip) r_pow[ip] = r*r_pow[ip-1];
00256    if (z != z_pow[1]) for (ip = 1; ip < max_nz; ++ip) z_pow[ip] = z*z_pow[ip-1];
00257 
00258    for (ip = 0; ip < (int)data.size(); ++ip) {
00259       if (is_off[ip]) continue;
00260       term = 0.;
00261       for (it = 0; it < (int)data[ip].size(); ++it) {
00262          term += data[ip][it].coeff
00263                * r_pow[data[ip][it].np[0]]
00264                * z_pow[data[ip][it].np[1]];
00265       }
00266       rez += *C * term;
00267       ++C;
00268    }
00269    
00270    return rez;
00271 }
00272 
00273 //_______________________________________________________________________________
00274 double *rz_poly::GetVVal(double r, double z, double *rez_out)
00275 {
00276 //return an array of doubleype with values of the basis functions in the point
00277 //(r,z). In a case if rez_out != 0, the rez_out array must be long enough to fit
00278 //in n_active elements. In a case if rez_out == 0, a new array of n_active length
00279 //is created; it is in user's responsibility to free the memory after all;
00280 //
00281    if (r_pow == 0) return 0;
00282    
00283    double term;
00284    int ip, it;
00285 
00286    double *rez;
00287    if (rez_out) rez = rez_out;
00288    else rez = new double [n_active];
00289 
00290    double *pnt = rez;
00291    
00292    if (r != r_pow[1]) for (ip = 1; ip < max_nr; ++ip) r_pow[ip] = r*r_pow[ip-1];
00293    if (z != z_pow[1]) for (ip = 1; ip < max_nz; ++ip) z_pow[ip] = z*z_pow[ip-1];
00294 
00295    for (ip = 0; ip < (int)data.size(); ++ip) {
00296       if (is_off[ip]) continue;
00297       term = 0.;
00298       for (it = 0; it < (int)data[ip].size(); ++it) {
00299          term += data[ip][it].coeff
00300                * r_pow[data[ip][it].np[0]]
00301                * z_pow[data[ip][it].np[1]];
00302       }
00303       *pnt = term;
00304       ++pnt;
00305    }
00306    
00307    return rez;
00308 }
00309 
00310 //_______________________________________________________________________________
00311 double *rz_poly::Expand(double *C)
00312 {
00313 //Take C[n_active] - reduced vector of coefficients and return pointer to 
00314 //expanded vector of coefficients of the data.size() length. It is in user's
00315 //responsibility to free the memory after all;
00316 //
00317    double *rez = new double [data.size()];
00318    for (int ip = 0; ip < (int)data.size(); ++ip) {
00319       if (is_off[ip]) rez[ip] = 0.;
00320       else {
00321          rez[ip] = *C;
00322          ++C;
00323       }
00324    }
00325    return rez;
00326 }
00327