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