Go to the documentation of this file.00001 #include "poly2d_base.h"
00002
00003 using namespace magfieldparam;
00004
00006
00007
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
00030
00031
00032
00034
00035
00036 double poly2d_base::rval = 0.;
00037 double poly2d_base::zval = 0.;
00038
00039 double **poly2d_base::rz_pow = 0;
00040 unsigned poly2d_base::NTab = 0;
00041 unsigned poly2d_base::NPwr = 0;
00042
00043 bool poly2d_base::rz_set = false;
00044
00045 const double poly2d_base::MIN_COEFF = DBL_EPSILON;
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()) {
00053 if (max_pwr >= NPwr) NPwr = GetMaxPow();
00054 } else {
00055 if (rz_pow) {
00056 delete [] rz_pow[0];
00057 delete [] rz_pow;
00058 }
00059 rz_pow = 0;
00060 rval = zval = 0.;
00061 NPwr = 0;
00062 NTab = 0;
00063 rz_set = false;
00064
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
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
00249
00250
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
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
00275
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
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