File indexing completed on 2024-04-06 12:22:35
0001 #include <typeinfo>
0002 #include "rz_harm_poly.h"
0003 #include <cstdlib>
0004
0005 using namespace magfieldparam;
0006
0007
0008
0009
0010
0011
0012
0013
0014 unsigned rz_harm_poly::Cnt = 0;
0015 double rz_harm_poly::phival = -11111.;
0016 bool rz_harm_poly::phi_set = false;
0017 unsigned rz_harm_poly::MaxM = 0;
0018
0019 unsigned rz_harm_poly::TASize = 0;
0020 trig_pair *rz_harm_poly::TrigArr = nullptr;
0021
0022
0023 rz_harm_poly::rz_harm_poly(const unsigned N) {
0024
0025
0026
0027 unsigned nz = N, nr = 0, nv = 0;
0028 poly2d_term v3(1. / N, nr, nz);
0029
0030 data = std::vector<poly2d_term>((N + 2) / 2, v3);
0031
0032 while (nz >= 2) {
0033 nz -= 2;
0034 nr += 2;
0035 nv += 1;
0036 data[nv].coeff = -data[nv - 1].coeff * (nz + 1) * (nz + 2) / (nr * nr);
0037 data[nv].np[0] = nr;
0038 data[nv].np[1] = nz;
0039 }
0040 max_pwr = N;
0041 if (max_pwr > NPwr) {
0042 NPwr = max_pwr;
0043 rz_set = false;
0044 phi_set = false;
0045 }
0046 L = N;
0047 M = 0;
0048 poly2d_base_set.insert(this);
0049 ++Cnt;
0050 }
0051
0052
0053 rz_harm_poly::~rz_harm_poly() {
0054 if (--Cnt) {
0055 if (std::abs(M) >= int(MaxM)) {
0056 M = 0;
0057 MaxM = GetMaxM();
0058 }
0059 } else {
0060 if (TrigArr)
0061 delete[] TrigArr;
0062 TrigArr = nullptr;
0063 TASize = 0;
0064 MaxM = 0;
0065 phival = -11111.;
0066 phi_set = false;
0067 }
0068 }
0069
0070
0071 int rz_harm_poly::GetMaxM() {
0072
0073
0074 int M_cur, M_max = 0;
0075 for (auto const &poly : poly2d_base_set) {
0076 if (typeid(*poly) == typeid(rz_harm_poly)) {
0077 M_cur = std::abs(static_cast<rz_harm_poly const *>(poly)->M);
0078 if (M_cur > M_max)
0079 M_max = M_cur;
0080 }
0081 }
0082 return M_max;
0083 }
0084
0085
0086 void rz_harm_poly::SetPhi(const double phi) {
0087
0088
0089
0090 if (MaxM >= TASize) {
0091 SetTrigArrSize(MaxM + 1);
0092 FillTrigArr(phi);
0093 } else if (phi != phival)
0094 FillTrigArr(phi);
0095 phival = phi;
0096 phi_set = true;
0097 }
0098
0099
0100 void rz_harm_poly::SetTrigArrSize(const unsigned N) {
0101
0102
0103 if (N <= TASize)
0104 return;
0105 if (TrigArr)
0106 delete[] TrigArr;
0107 TrigArr = new trig_pair[N];
0108 (*TrigArr) = trig_pair(1., 0.);
0109 TASize = N;
0110 phi_set = false;
0111 }
0112
0113
0114 void rz_harm_poly::FillTrigArr(const double phi) {
0115
0116 if (!TrigArr)
0117 return;
0118 trig_pair tp(phi);
0119 TrigArr[1] = tp;
0120 for (unsigned jp = 2; jp <= MaxM; ++jp)
0121 TrigArr[jp] = TrigArr[jp - 1].Add(tp);
0122 }
0123
0124
0125 void rz_harm_poly::PrintTrigArr(std::ostream &out, const std::streamsize prec) {
0126 out << "TrigArr: TASize = " << TASize << "\tMaxM = " << MaxM << std::endl;
0127 if (TrigArr) {
0128 if (MaxM < TASize) {
0129 unsigned jm;
0130 std::streamsize old_prec = out.precision(), wdt = prec + 7;
0131 out.precision(prec);
0132 out << "M: ";
0133 for (jm = 0; jm <= MaxM; ++jm) {
0134 out << std::setw(wdt) << std::left << jm;
0135 }
0136 out << "|\nCos_M: ";
0137 for (jm = 0; jm <= MaxM; ++jm) {
0138 out << std::setw(wdt) << std::left << TrigArr[jm].CosPhi;
0139 }
0140 out << "|\nSin_M: ";
0141 for (jm = 0; jm <= MaxM; ++jm) {
0142 out << std::setw(wdt) << std::left << TrigArr[jm].SinPhi;
0143 }
0144 out << "|" << std::endl;
0145 out.precision(old_prec);
0146 } else {
0147 out << "\tTrigArr size is not adjusted." << std::endl;
0148 }
0149 } else {
0150 out << "\tTrigArr is not allocated." << std::endl;
0151 }
0152 }
0153
0154
0155 rz_harm_poly rz_harm_poly::LadderUp() {
0156
0157
0158 rz_harm_poly p_out;
0159 p_out.data.reserve(2 * L);
0160 unsigned it;
0161 poly2d_term term;
0162
0163
0164 for (it = 0; it < data.size(); ++it) {
0165 term = data[it];
0166 if (term.np[0]) {
0167 term.coeff *= int(term.np[0]) - M;
0168 --term.np[0];
0169 ++term.np[1];
0170 p_out.data.push_back(term);
0171 }
0172 }
0173 for (it = 0; it < data.size(); ++it) {
0174 term = data[it];
0175 if (term.np[1]) {
0176 term.coeff *= -(int)term.np[1];
0177 --term.np[1];
0178 ++term.np[0];
0179 p_out.data.push_back(term);
0180 }
0181 }
0182 p_out.Collect();
0183 if (!p_out.data.empty()) {
0184 p_out.L = L;
0185 p_out.M = M + 1;
0186 if (std::abs(p_out.M) > int(MaxM))
0187 MaxM = std::abs(p_out.M);
0188 p_out.Scale(1. / sqrt(double((L - M) * (L + M + 1))));
0189 }
0190 return p_out;
0191 }
0192
0193
0194 rz_harm_poly rz_harm_poly::LadderDwn() {
0195
0196
0197 rz_harm_poly p_out;
0198 p_out.data.reserve(2 * L);
0199 unsigned it;
0200 poly2d_term term;
0201
0202
0203 for (it = 0; it < data.size(); ++it) {
0204 term = data[it];
0205 if (term.np[0]) {
0206 term.coeff *= -int(term.np[0]) - M;
0207 --term.np[0];
0208 ++term.np[1];
0209 p_out.data.push_back(term);
0210 }
0211 }
0212 for (it = 0; it < data.size(); ++it) {
0213 term = data[it];
0214 if (term.np[1]) {
0215 term.coeff *= term.np[1];
0216 --term.np[1];
0217 ++term.np[0];
0218 p_out.data.push_back(term);
0219 }
0220 }
0221 p_out.Collect();
0222 if (!p_out.data.empty()) {
0223 p_out.L = L;
0224 p_out.M = M - 1;
0225 if (std::abs(p_out.M) > int(MaxM))
0226 MaxM = std::abs(p_out.M);
0227 p_out.Scale(1. / sqrt(double((L + M) * (L - M + 1))));
0228 }
0229 return p_out;
0230 }