CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/MagneticField/ParametrizedEngine/plugins/poly2d_base.cc

Go to the documentation of this file.
00001 #include "poly2d_base.h"
00002 
00003 using namespace magfieldparam;
00004 
00006 //                                                                             //
00007 //  The "poly2d_term" represent a term of a polynomial of 2 variables.         //
00008 //                                                                             //
00010 
00011 //_______________________________________________________________________________
00012 void poly2d_term::Print(std::ostream &out, bool first_term)
00013 {
00014    if (first_term) out << coeff;
00015    else if (coeff > 0.) out << " + " << coeff;
00016         else out << " - " << -coeff;
00017    if (np[0] != 0) {
00018       out << "*r";
00019       if (np[0] != 1) out << "^" << np[0];
00020    }
00021    if (np[1] != 0) {
00022       out << "*z";
00023       if (np[1] != 1) out << "^" << np[1];
00024    }
00025 }
00026 
00028 //                                                                             //
00029 //  Base class that represent a polynomial of 2 variables. It isn't supposed   //
00030 //  to be used directly and provides no way of setting coefficients directly.  //
00031 //  Such methods must be defined in derived classes.                           //
00032 //                                                                             //
00034 
00035 //_______________________________________________________________________________
00036 double     poly2d_base::rval   = 0.; //Last values of r and z used
00037 double     poly2d_base::zval   = 0.;
00038 
00039 double   **poly2d_base::rz_pow = 0;  //table with calculated r^n*z^m values
00040 unsigned   poly2d_base::NTab   = 0;  //rz_pow table size
00041 unsigned   poly2d_base::NPwr   = 0;  //max power in use by CLASS
00042 
00043 bool       poly2d_base::rz_set = false;
00044 
00045 const double poly2d_base::MIN_COEFF = DBL_EPSILON; //Thresh. for coeff == 0
00046 std::set<poly2d_base*> poly2d_base::poly2d_base_set;
00047 
00048 //_______________________________________________________________________________
00049 poly2d_base::~poly2d_base()
00050 {
00051    poly2d_base_set.erase(poly2d_base_set.find(this));
00052    if(poly2d_base_set.size()) { //some objects left
00053       if (max_pwr >= NPwr) NPwr = GetMaxPow();
00054    } else {
00055       if (rz_pow) {
00056          delete [] rz_pow[0]; //deleting the last instance -> memory cleanup
00057          delete [] rz_pow;
00058       }
00059       rz_pow = 0;
00060       rval = zval = 0.;
00061       NPwr = 0;
00062       NTab = 0;
00063       rz_set = false;
00064 //      poly2d_base_set.resize(0);
00065    }
00066 }
00067 
00068 //_______________________________________________________________________________
00069 void poly2d_base::SetTabSize(const unsigned N)
00070 {
00071    if (N <= NTab) return;
00072    if (rz_pow) {
00073       delete [] rz_pow[0];
00074       delete [] rz_pow;
00075    }
00076    rz_pow    = new double* [N];
00077    unsigned jr, dN = N*(N+1)/2;
00078    rz_pow[0] = new double  [dN];
00079    memset(rz_pow[0], 0, dN*sizeof(double));
00080    rz_pow[0][0] = 1.;
00081    for (jr = 1, dN = N; jr < N; ++jr, --dN) {
00082       rz_pow[jr] = rz_pow[jr-1] + dN;
00083    }
00084    rval = zval = 0.;
00085    NTab = N;
00086 }
00087 
00088 //_______________________________________________________________________________
00089 void poly2d_base::FillTable(const double r, const double z)
00090 {
00091    if (!rz_pow) return;
00092    unsigned jr, jz;
00093    for (jz = 1; jz <= NPwr; ++jz) rz_pow[0][jz] = z*rz_pow[0][jz-1];
00094    for (jr = 1; jr <= NPwr; ++jr) {
00095       for (jz = 0; jz <= (NPwr - jr); ++jz) {
00096          rz_pow[jr][jz] = r*rz_pow[jr-1][jz];
00097       }
00098    }
00099 }
00100 
00101 //_______________________________________________________________________________
00102 int poly2d_base::GetMaxPow()
00103 {
00104    int curp, maxp = 0;
00105    std::set<poly2d_base*>::iterator it;
00106 
00107    for (it = poly2d_base_set.begin(); it != poly2d_base_set.end(); ++it) {
00108       curp = (*it)->max_pwr;
00109       if (curp > maxp) maxp = curp;
00110    }
00111    return maxp;
00112 }
00113 
00114 //_______________________________________________________________________________
00115 void poly2d_base::AdjustTab()
00116 {
00117    NPwr = GetMaxPow();
00118    if (NPwr >= NTab) SetTabSize(NPwr+1);
00119 }
00120 
00121 //_______________________________________________________________________________
00122 void poly2d_base::PrintTab(std::ostream &out, const std::streamsize prec)
00123 {
00124    out << "poly2d_base table size NTab = " << NTab
00125        << "\tmax. power NPwr = " << NPwr << std::endl;
00126    if (rz_pow) {
00127       if (NPwr < NTab) {
00128          std::streamsize old_prec = out.precision(), wdt = prec+7; 
00129          out.precision(prec);
00130          out << "Table content:" << std::endl;
00131          unsigned jr, jz;
00132          for (jr = 0; jr <= NPwr; ++jr) {
00133             for (jz = 0; jz <= (NPwr-jr); ++jz) {
00134                out << std::setw(wdt) << std::left << rz_pow[jr][jz];
00135             }
00136             out << "|" << std::endl;
00137          }
00138          out.precision(old_prec);
00139       } else {
00140          out << "\tTable size is not adjusted." << std::endl;
00141       }
00142    } else {
00143       out << "\tTable is not allocated." << std::endl;
00144    }
00145 }
00146 
00147 //_______________________________________________________________________________
00148 void poly2d_base::SetPoint(const double r, const double z)
00149 {
00150    if (!Count()) return;
00151    if (NPwr >= NTab) { SetTabSize(NPwr+1); FillTable(r, z);}
00152    else if ((r != rval) || (z != zval)) FillTable(r, z);
00153    rz_set = true;
00154 }
00155 
00156 //_______________________________________________________________________________
00157 double poly2d_base::Eval()
00158 {
00159    double S = 0.;
00160    for (unsigned j = 0; j < data.size(); ++j)
00161       S += data[j].coeff*rz_pow[data[j].np[0]][data[j].np[1]];
00162    return S;
00163 }
00164 
00165 //_______________________________________________________________________________
00166 void poly2d_base::Collect()
00167 {
00168    if (!(data.size())) return;
00169 
00170    unsigned j1, j2, rpow, zpow, noff = 0, jend = data.size();
00171    double C;
00172    std::vector<bool> mask(jend, false);
00173    max_pwr = 0;
00174 
00175    for (j1 = 0; j1 < jend; ++j1) {
00176       if (mask[j1]) continue;
00177       C = data[j1].coeff;
00178       rpow = data[j1].np[0];
00179       zpow = data[j1].np[1];
00180       for (j2 = j1+1; j2 < jend; ++j2) {
00181          if (mask[j2]) continue;
00182          if ((rpow == data[j2].np[0]) && (zpow == data[j2].np[1])) {
00183             C += data[j2].coeff;
00184             mask[j2] = true;
00185             ++noff;
00186          }
00187       }
00188       if (fabs(C) > MIN_COEFF) {
00189          data[j1].coeff = C;
00190          if ((rpow = rpow+zpow) > max_pwr) max_pwr = rpow;
00191       } else {
00192          mask[j1] = true;
00193          ++noff;
00194       }
00195    }
00196    std::vector<poly2d_term> newdata; newdata.reserve(jend - noff);
00197    for (j1 = 0; j1 < jend; ++j1) {
00198       if (!(mask[j1])) newdata.push_back(data[j1]);
00199    }
00200    data.swap(newdata);
00201 }
00202 
00203 //_______________________________________________________________________________
00204 void poly2d_base::Print(std::ostream &out, const std::streamsize prec)
00205 {
00206    if (!data.size()) {
00207       out << "\"poly2d_base\" object contains no terms." << std::endl;
00208       return;
00209    }
00210    out << data.size() << " terms; max. degree = " << max_pwr << ":" << std::endl;
00211    std::streamsize old_prec = out.precision();
00212    out.precision(prec);
00213    data[0].Print(out);
00214    for (unsigned it = 1; it < data.size(); ++it) {
00215          data[it].Print(out, false);
00216    }
00217    out << std::endl;
00218    out.precision(old_prec);
00219 }
00220 
00221 //_______________________________________________________________________________
00222 void poly2d_base::Diff(int nvar)
00223 {
00224 //differentiate the polynomial by variable nvar.
00225 //
00226    poly2d_term  v3;
00227    std::vector<poly2d_term> newdata;
00228    newdata.reserve(data.size());
00229    unsigned cur_pwr = 0, maxp = 0, oldp = max_pwr;
00230    for (unsigned it = 0; it < data.size(); ++it) {
00231       v3 = data[it];
00232       v3.coeff *= v3.np[nvar];
00233       if (v3.coeff != 0.) {
00234          --v3.np[nvar];
00235          newdata.push_back(v3);
00236          if ((cur_pwr = v3.np[0] + v3.np[1]) > maxp) maxp = cur_pwr;
00237       }
00238    }
00239    newdata.resize(newdata.size());
00240    max_pwr = maxp;
00241    data.swap(newdata);
00242    if (oldp >= NPwr) NPwr = GetMaxPow();
00243 }
00244 
00245 //_______________________________________________________________________________
00246 void poly2d_base::Int(int nvar)
00247 {
00248 //Integrate the polynomial by variable# nvar. Doesn't remove terms
00249 //with zero coefficients; if you suspect they can appear, use Compress()
00250 //after the integration.
00251 //
00252    for (unsigned it = 0; it < data.size(); ++it) {
00253       data[it].coeff /= ++data[it].np[nvar];
00254    }
00255    ++max_pwr;
00256    if (max_pwr > NPwr) NPwr = GetMaxPow();
00257 }
00258 
00259 //_______________________________________________________________________________
00260 void poly2d_base::IncPow(int nvar)
00261 {
00262 //Multiply the polynomial by variable# nvar
00263 //
00264    for (unsigned it = 0; it < data.size(); ++it) {
00265       ++data[it].np[nvar];
00266    }
00267    ++max_pwr;
00268    if (max_pwr > NPwr) NPwr = GetMaxPow();
00269 }
00270 
00271 //_______________________________________________________________________________
00272 void poly2d_base::DecPow(int nvar)
00273 {
00274 //Divide the polynomial by variable# nvar. Remove terms with zero coefficients
00275 //and also terms where the initial power of nvar is equal zero
00276 //
00277    poly2d_term  v3;
00278    std::vector<poly2d_term> newdata;
00279    newdata.reserve(data.size());
00280    unsigned cur_pwr = 0, maxp = 0, oldp = max_pwr;
00281    for (unsigned it = 0; it < data.size(); ++it) {
00282       v3 = data[it];
00283       if ((v3.coeff != 0.) && (v3.np[nvar] > 0)) {
00284          --v3.np[nvar];
00285          newdata.push_back(v3);
00286          if ((cur_pwr = v3.np[0] + v3.np[1]) > maxp) maxp = cur_pwr;
00287       }
00288    }
00289    newdata.resize(newdata.size());
00290    max_pwr = maxp;
00291    data.swap(newdata);
00292    if (oldp >= NPwr) NPwr = GetMaxPow();
00293 }
00294    
00295 //_______________________________________________________________________________
00296 void poly2d_base::Scale(const double C)
00297 {
00298 //Multiply the polynomial by a constant.
00299 //
00300    if (C != 0.) {
00301       for (unsigned it = 0; it < data.size(); ++it) {
00302          data[it].coeff *= C;
00303       }
00304    } else data.resize(0);
00305 }
00306