00001 #include "AML/AMLUtilities.hpp"
00002 #include "UAP/UAPUtilities.hpp"
00003 #include <cmath>
00004
00005 using namespace std;
00006 namespace BU = BasicUtilities;
00007
00008
00009
00010
00011 bool AMLUtilities::inAMLNameSpace (UAPNode* node) {
00012 return inAMLNameSpace (node->getXMLURI());
00013 }
00014
00015 bool AMLUtilities::inAMLNameSpace (const string& name) {
00016 if (name == "" || name == "http://lepp.cornell.edu/aml" ||
00017 name.substr(0, 29) == "{http://lepp.cornell.edu/aml}") return true;
00018 return false;
00019 }
00020
00021
00022
00023
00024 AMLUtilities::AMLUtilities() {
00025 init_valid_attributes();
00026 }
00027
00028
00029
00030
00031 bool AMLUtilities::getSectorArgList (UAPNode* sector, StrList& arg_list) {
00032
00033 arg_list.clear();
00034
00035 string args = sector->getAttributeString("args");
00036 if (args == "") return true;
00037
00038 string arg;
00039 size_t ix;
00040 for (ix=1; ix != string::npos;) {
00041 if ((ix = args.find(",")) != string::npos) {
00042 arg = args.substr(0, ix);
00043 args.erase(0, ix+1);
00044 } else {
00045 arg = args;
00046 }
00047 while (arg[0] == ' ') arg.erase(0, 1);
00048 while (arg[arg.length()-1] == ' ') arg.erase(arg.length()-1, 1);
00049 if (arg.find(" ") != string::npos) {
00050 info_out.error ("SECTOR ARGUMENT HAS BLANK SPACE", sector->toString());
00051 return false;
00052 }
00053 arg_list.push_back(arg);
00054 }
00055 return true;
00056
00057 }
00058
00059
00060
00061
00062 void AMLUtilities::controllerBookkeeper (UAPNode* expand_root) {
00063
00064
00065
00066 UAPUtilities utilities(expand_root);
00067
00068 NodeVec controllers = expand_root->getSubNodesByName("controller");
00069 for (NodeVecIter ic = controllers.begin(); ic != controllers.end(); ic++) {
00070 UAPNode* controller = *ic;
00071 string dflt_attribute = controller->getAttributeString("default_attribute");
00072 string dflt_expression = controller->getAttributeString("expression");
00073
00074
00075 NodeVec c_children = controller->getChildren();
00076 for (NodeVecIter icc = c_children.begin(); icc != c_children.end(); icc++) {
00077 UAPNode* c_child = *icc;
00078
00079
00080
00081 if (!inAMLNameSpace(c_child)) continue;
00082 if (c_child->getName() != "slave") {
00083 info_out.error ("Child: " + c_child->toString(),
00084 "Is not a <slave> of controller: ",
00085 controller->toStringTree());
00086 continue;
00087 }
00088
00089
00090
00091 string exp = c_child->getAttributeString("expression");
00092 if (exp == "") exp == dflt_expression;
00093 if (exp == "") {
00094 info_out.error ("No expression for slave: " + c_child->toString(),
00095 "Of controller: ", controller->toString());
00096 continue;
00097 }
00098
00099 double value = utilities.evaluate(exp);
00100
00101
00102
00103 string attrib = dflt_attribute;
00104 string target = c_child->getAttributeString("target");
00105 if (target.find("[") != string::npos) {
00106 attrib = target.substr(target.find("["));
00107 attrib.erase(attrib.size()-1);
00108 }
00109
00110 if (target == "") {
00111 info_out.error ("NO TARGET ATTRIBUTE FOR SLAVE: " + c_child->toStringTree(),
00112 "OF CONTROLLER: " + controller->toStringTree());
00113 continue;
00114 }
00115
00116
00117
00118 NodeVec eles = c_child->getList(SLAVE);
00119 for (NodeVecIter is = eles.begin(); is != eles.end(); is++) {
00120 UAPNode* ele = *is;
00121
00122
00123
00124 UAPNode* attrib_node = Twig::getLocalSubNode(ele, attrib, true);
00125 if (!attrib_node) {
00126 info_out.error ("Reference to invalid attribute in controller: " + attrib,
00127 "In controller: " + controller->toStringTree());
00128 continue;
00129 }
00130
00131 bool ok;
00132 attrib_node->addAttribute("actual", BU::double_to_string(value, ok));
00133
00134 }
00135
00136 }
00137
00138 }
00139
00140
00141
00142 return;
00143
00144 }
00145
00146
00147
00148
00149 bool AMLUtilities::splitElement (UAPNode* machine_root, double s_split,
00150 NodeVecIter& iter, double tol) {
00151
00152 bool ok;
00153
00154 UAPNode* tracking_root = machine_root->getChildByName("tracking_lattice");
00155 UAPNode* master_root = machine_root->getChildByName("master_list");
00156 NodeVec& lattice = tracking_root->getChildren();
00157 iter = lattice.end();
00158
00159
00160
00161 if (s_split < getAMLAttributeNumericValue(lattice.front(), "s@actual", ok) - tol) {
00162 info_out.error ("Position of split not within the lattice: " +
00163 BU::double_to_string(s_split, ok));
00164 return false;
00165 }
00166
00167 if (s_split > getAMLAttributeNumericValue(lattice.back(), "s@actual", ok) + tol) {
00168 info_out.error ("Position of split not within the lattice: " +
00169 BU::double_to_string(s_split, ok));
00170 return false;
00171 }
00172
00173
00174
00175
00176 NodeVecIter in;
00177 double s1;
00178 for (in = lattice.begin(); in != lattice.end(); in++) {
00179 s1 = getAMLAttributeNumericValue(*in, "s@actual", ok);
00180 if (!ok) {
00181 iter = lattice.begin();
00182 return false;
00183 }
00184 if (fabs(s1 - s_split) < tol) {
00185 iter = ++in;
00186 return false;
00187 }
00188 if (s1+tol > s_split) break;
00189 }
00190
00191
00192
00193 UAPNode* ele = *in;
00194
00195 double len = getAMLAttributeNumericValue(ele, "length@actual", ok);
00196 double s0 = s1 - len;
00197
00198
00199
00200
00201 string len1_str = BU::double_to_string(s_split - s0, ok);
00202 string s1_str = BU::double_to_string(s_split, ok);
00203 string len2_str = BU::double_to_string(s1 - s_split, ok);
00204 string s2_str = BU::double_to_string(s1, ok);
00205 string ele_name = ele->getAttributeString("name");
00206
00207 UAPNode* slave1;
00208 UAPNode* slave2;
00209
00210 if (ele->getAttributeString("slave_rank") != "SUPER_SLAVE") {
00211 UAPNode* super_ele = master_root->addChildCopy(ele);
00212 super_ele->addAttribute("lord_rank", "SUPER_LORD");
00213 transferLordSlaveLinks(ele, super_ele);
00214
00215 slave1 = tracking_root->addChild("element", ele);
00216 slave1->add(MASTER, super_ele);
00217 super_ele->add(SLAVE, slave1);
00218
00219 slave2 = tracking_root->addChild("element", ele);
00220 slave2->add(MASTER, super_ele);
00221 super_ele->add(SLAVE, slave2);
00222
00223 form_super_slave_names (super_ele);
00224
00225 slave1->addAttribute("slave_rank", "SUPER_SLAVE");
00226 slave1->addChild("length")->addAttribute("actual", len1_str);
00227 slave1->addChild("s")->addAttribute("actual", s1_str);
00228
00229 slave2->addAttribute("slave_rank", "SUPER_SLAVE");
00230 slave2->addChild("length")->addAttribute("actual", len2_str);
00231 slave2->addChild("s")->addAttribute("actual", s2_str);
00232
00233 iter = --in;
00234 ele->deleteNode();
00235
00236
00237
00238 } else {
00239 slave1 = tracking_root->addChildCopy(ele, ele);
00240 slave2 = ele;
00241
00242 slave1->addAttribute("name", ele_name + "|1");
00243 UAPNode* len_node = slave1->getChildByName("length");
00244 len_node->getAttribute("actual")->setValue(len1_str);
00245 slave1->getChildByName("s")->getAttribute("actual")->setValue(s1_str);
00246
00247 slave2->addAttribute("name", ele_name + "|2");
00248 len_node = slave2->getChildByName("length");
00249 len_node->getAttribute("actual")->setValue(len2_str);
00250 len_node->removeAttribute("design");
00251 len_node->removeAttribute("err");
00252 slave2->getChildByName("s")->getAttribute("actual")->setValue(s2_str);
00253
00254
00255
00256
00257 NodeVec m_list = slave2->getList(MASTER);
00258 for (NodeVecIter im = m_list.begin(); im != m_list.end(); im++) {
00259 UAPNode* master = *im;
00260 master->add(SLAVE, slave1, slave2);
00261 }
00262
00263 iter = in;
00264 form_super_slave_names (slave1);
00265 }
00266
00267
00268
00269 UAPNode* len_node = slave1->getChildByName("length");
00270 len_node->removeAttribute("design");
00271 len_node->removeAttribute("err");
00272
00273 len_node = slave2->getChildByName("length");
00274 len_node->removeAttribute("design");
00275 len_node->removeAttribute("err");
00276
00277
00278 }
00279
00280
00281
00282
00283 void AMLUtilities::form_super_slave_names (UAPNode* ele) {
00284
00285
00286
00287 if (ele->getAttributeString("slave_rank") == "SUPER_SLAVE") {
00288 NodeVec lords = ele->getList(MASTER);
00289 for (NodeVecIter ie = lords.begin(); ie != lords.end(); ie++) {
00290 form_super_slave_names(*ie);
00291 }
00292 return;
00293 }
00294
00295
00296
00297 if (ele->getAttributeString("lord_rank") != "SUPER_LORD") return;
00298
00299
00300
00301 typedef map<string, int> IntMap;
00302 typedef map<string, int>::iterator IntMapIter;
00303
00304 IntMap slave_map;
00305
00306 NodeVec slaves = ele->getList(SLAVE);
00307 for (NodeVecIter is = slaves.begin(); is != slaves.end(); is++) {
00308 UAPNode* slave = *is;
00309 NodeVec lords = slave->getList(MASTER);
00310 string slave_name;
00311 for (NodeVecIter im = lords.begin(); im != lords.end(); im++) {
00312 if (im == lords.begin() || im != --lords.end())
00313 slave_name += (*im)->getAttributeString("name") + "|";
00314 else
00315 slave_name += (*im)->getAttributeString("name");
00316 }
00317 slave->addAttribute("name", slave_name);
00318 if (BU::found(slave_map, slave_name))
00319 ++(slave_map[slave_name]);
00320 else
00321 slave_map[slave_name] = 0;
00322
00323 }
00324
00325
00326
00327 for (IntMapIter ia = slave_map.begin(); ia != slave_map.end(); ia++) {
00328 if (ia->second == 0) continue;
00329 ia->second = 1;
00330 }
00331
00332 bool ok;
00333
00334 for (NodeVecIter is = slaves.begin(); is != slaves.end(); is++) {
00335 UAPNode* slave = *is;
00336 string slave_name = slave->getAttributeString("name");
00337 if (slave_map[slave_name] == 0) continue;
00338 string this_name = slave_name;
00339 if (this_name[this_name.size()-1] != '|') this_name += "|";
00340 this_name += BU::int_to_string(slave_map[slave_name], ok);
00341 slave_map[slave_name]++;
00342 slave->addAttribute("name", this_name);
00343 }
00344
00345 return;
00346
00347 }
00348
00349
00350
00351
00352 void AMLUtilities::transferLordSlaveLinks (UAPNode* old_node, UAPNode* new_node) {
00353
00354
00355
00356 NodeVec m_list = old_node->getList(MASTER);
00357 for (NodeVecIter im = m_list.begin(); im != m_list.end(); im++) {
00358 UAPNode* master = *im;
00359 NodeVec& s_list = master->getList(SLAVE);
00360 for (NodeVecIter is = s_list.begin(); is != s_list.end(); is++) {
00361 UAPNode* slave = *is;
00362 if (slave == old_node) {
00363 *is = new_node;
00364 }
00365 }
00366 }
00367
00368
00369
00370 NodeVec c_list = old_node->getList(CONTROLLER);
00371 for (NodeVecIter ic = c_list.begin(); ic != c_list.end(); ic++) {
00372 UAPNode* control = *ic;
00373 NodeVec& s_list = control->getList(SLAVE);
00374 for (NodeVecIter is = s_list.begin(); is != s_list.end(); is++) {
00375 UAPNode* slave = *is;
00376 if (slave == old_node) {
00377 *is = new_node;
00378 }
00379 }
00380 }
00381
00382
00383
00384 NodeVec s_list = old_node->getList(SLAVE);
00385 for (NodeVecIter is = s_list.begin(); is != s_list.end(); is++) {
00386 UAPNode* slave = *is;
00387
00388 NodeVec& m_list = slave->getList(MASTER);
00389 for (NodeVecIter im = m_list.begin(); im != m_list.end(); im++) {
00390 UAPNode* master = *im;
00391 if (master == old_node) {
00392 *im = new_node;
00393 }
00394 }
00395
00396 NodeVec& c_list = slave->getList(CONTROLLER);
00397 for (NodeVecIter ic = c_list.begin(); ic != c_list.end(); ic++) {
00398 UAPNode* control = *ic;
00399 if (control == old_node) {
00400 *ic = new_node;
00401 }
00402 }
00403
00404 }
00405
00406 return;
00407
00408 }
00409
00410
00411
00412
00413 double AMLUtilities::getAMLAttributeNumericValue (UAPNode* root,
00414 string attrib_name, bool& ok) {
00415
00416
00417
00418 string value_str = getAMLAttributeString(root, attrib_name, ok);
00419 if (!ok) {
00420 ok = true;
00421 return 0;
00422 }
00423
00424
00425
00426 return BU::string_to_double(value_str, ok);
00427 }
00428
00429
00430
00431
00432 string AMLUtilities::getAMLAttributeString (UAPNode* root,
00433 string attrib_name, bool& ok) {
00434
00435 ok = false;
00436
00437
00438
00439
00440
00441 Twig twig;
00442 if (!twig.fromString(attrib_name)) return "";
00443
00444 UAPNode* attrib_node = twig.getSubNode(root);
00445 if (!attrib_node) return "";
00446
00447
00448
00449 UAPAttribute* attrib = attrib_node->getAttribute(twig.target_attribute);
00450 if (!attrib) return "";
00451 ok = true;
00452 return attrib->getValue();
00453
00454 }
00455
00456
00457
00458
00459
00460 bool AMLUtilities::validAttribute (const string& attribute) {
00461 return true;
00462 return BU::found(valid_attributes, attribute);
00463 }
00464
00465
00466
00467
00468 void AMLUtilities::init_valid_attributes () {
00469
00470 wild_attributes.clear();
00471 valid_attributes.clear();
00472
00473 add_valid_attribute ("s");
00474 add_valid_attribute ("length");
00475 add_valid_attribute ("quadrupole:k");
00476 add_valid_attribute ("sextupole:k");
00477 add_valid_attribute ("octupole:k");
00478 add_valid_attribute ("solenoid:ksol");
00479
00480 add_valid_attribute ("orientation*");
00481 add_valid_attribute ("quadrupole:orientation*");
00482 add_valid_attribute ("sextupole:orientation*");
00483 add_valid_attribute ("octupole:orientation*");
00484 add_valid_attribute ("solenoid:orientation*");
00485 add_valid_attribute ("rf_cavity:orientation*");
00486 add_valid_attribute ("multipole:orientation*");
00487 add_valid_attribute ("thick_multipole:orientation*");
00488 add_valid_attribute ("beambeam:orientation*");
00489 add_valid_attribute ("wiggler:orientation*");
00490 add_valid_attribute ("electric_kicker:orientation*");
00491 add_valid_attribute ("kicker:orientation*");
00492 add_valid_attribute ("bend:orientation*");
00493
00494 add_valid_attribute ("*orientation:tilt");
00495 add_valid_attribute ("*orientation:x_offset");
00496 add_valid_attribute ("*orientation:y_offset");
00497 add_valid_attribute ("*orientation:s_offset");
00498 add_valid_attribute ("*orientation:x_pitch");
00499 add_valid_attribute ("*orientation:y_pitch");
00500 add_valid_attribute ("*orientation:roll");
00501
00502 for (int i = 0; i < 21; i++) {
00503 ostringstream oss;
00504 oss << i;
00505 add_valid_attribute ("multipole:kl(n=" + oss.str() + ")");
00506 add_valid_attribute ("multipole:ksl(n=" + oss.str() + ")");
00507 add_valid_attribute ("multipole:kl_u(n=" + oss.str() + ")");
00508 add_valid_attribute ("multipole:ksl_u(n=" + oss.str() + ")");
00509 add_valid_attribute ("multipole:tilt(n=" + oss.str() + ")");
00510 add_valid_attribute ("scaled_multipole:k_coef(n=" + oss.str() + ")");
00511 add_valid_attribute ("scaled_multipole:ks_coef(n=" + oss.str() + ")");
00512 add_valid_attribute ("scaled_multipole:tilt(n=" + oss.str() + ")");
00513 }
00514
00515 add_valid_attribute ("aperture:xy_limit");
00516 add_valid_attribute ("aperture:x_limit");
00517 add_valid_attribute ("aperture:y_limit");
00518
00519 add_valid_attribute ("methods:tracking_method:name");
00520 add_valid_attribute ("methods:map_creation_method:name");
00521 add_valid_attribute ("methods:symplectify:name");
00522 add_valid_attribute ("methods:itegrator_order:name");
00523 add_valid_attribute ("methods:num_steps");
00524 add_valid_attribute ("methods:ds_step");
00525 add_valid_attribute ("methods:relative_tollerance");
00526 add_valid_attribute ("methods:absolute_tollerance");
00527
00528 add_valid_attribute ("wiggler:polarity");
00529
00530 add_valid_attribute ("rf_cavity:harmonic");
00531 add_valid_attribute ("rf_cavity:voltage");
00532 add_valid_attribute ("rf_cavity:phase0");
00533 add_valid_attribute ("rf_cavity:rf_freq");
00534 add_valid_attribute ("rf_cavity:e_loss");
00535
00536 add_valid_attribute ("electric_kicker:x_kick");
00537 add_valid_attribute ("electric_kicker:y_kick");
00538 add_valid_attribute ("electric_kicker:x_kick_u");
00539 add_valid_attribute ("electric_kicker:y_kick_u");
00540 add_valid_attribute ("electric_kicker:gap");
00541
00542 add_valid_attribute ("bend:angle");
00543 add_valid_attribute ("bend:g");
00544 add_valid_attribute ("bend:e1");
00545 add_valid_attribute ("bend:e2");
00546 add_valid_attribute ("bend:h1");
00547 add_valid_attribute ("bend:h2");
00548 add_valid_attribute ("bend:f_int1");
00549 add_valid_attribute ("bend:f_int2");
00550 add_valid_attribute ("bend:h_gap1");
00551 add_valid_attribute ("bend:h_gap2");
00552
00553 add_valid_attribute ("kicker:kick");
00554 add_valid_attribute ("kicker:x_kick");
00555 add_valid_attribute ("kicker:y_kick");
00556 add_valid_attribute ("kicker:bl_x_kick");
00557 add_valid_attribute ("kicker:bl_y_kick");
00558
00559 add_valid_attribute ("beambeam:sig_x");
00560 add_valid_attribute ("beambeam:sig_y");
00561 add_valid_attribute ("beambeam:charge");
00562
00563 }
00564
00565
00566
00567
00568 void AMLUtilities::add_valid_attribute (string attrib_str) {
00569
00570
00571
00572 size_t i = attrib_str.find("*");
00573 if (i == string::npos) {
00574 valid_attributes.push_back(attrib_str);
00575 return;
00576 }
00577
00578
00579
00580 if (i == attrib_str.size()-1) {
00581 string sub_str = attrib_str.substr(0,attrib_str.size()-1);
00582 wild_attributes.push_back(sub_str);
00583 return;
00584 }
00585
00586
00587
00588 if (i == 0) {
00589 attrib_str = attrib_str.substr(1);
00590 size_t ixc = attrib_str.find(":");
00591 string match_str = attrib_str.substr(0,ixc);
00592 string add_str = attrib_str.substr(ixc);
00593
00594 for (StrListIter iw = wild_attributes.begin(); iw != wild_attributes.end(); iw++) {
00595 string wild = *iw;
00596 size_t j = wild.find_last_of(":");
00597 ixc = 0;
00598 if (j != string::npos) ixc = j+1;
00599 if (wild.substr(ixc) == match_str) valid_attributes.push_back(wild + add_str);
00600 }
00601
00602 return;
00603 }
00604
00605 }