Skip to content

Commit 03ba2a6

Browse files
authored
Merge pull request #1179 from HelmutCERN/master
More flexible solenoid definition, resolve issue 1147
2 parents 88211ac + 6b12ebe commit 03ba2a6

File tree

9 files changed

+94
-33
lines changed

9 files changed

+94
-33
lines changed

src/mad_dict.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2034,6 +2034,7 @@ const char *const_element_def =
20342034
"harmon = [i, 0], "
20352035
"nbin = [i, 0], "
20362036
"magnet = [i, 0], "
2037+
"slice = [i, 1], "
20372038
"slot_id = [i, 0], "
20382039
"assembly_id = [i, 0], "
20392040
"model = [i, -1], "

src/mad_elem.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ make_element(const char* name, const char* parent, struct command* def, int flag
302302
warning("Multipole defined with non-zero length:", el->name);
303303
el->length = el_par_value("l", el);
304304
set_aperture_element(el, def);
305+
if(belongs_to_class(el,"solenoid")) check_set_consistent_solenoid(el,def);
305306
}
306307

307308
add_to_el_list(&el, def->mad8_type, element_list, flag);
@@ -1110,3 +1111,28 @@ add_to_el_list( /* adds element to alphabetic element list */
11101111
}
11111112
}
11121113

1114+
void check_set_consistent_solenoid(struct element *el, struct command* def)
1115+
{ // checking and if needed improving the element definition. Note that only nonzero ksi is shown in the twiss output, ks in twiss always zero
1116+
double l = el_par_value("l",el);
1117+
double ks = el_par_value("ks",el);
1118+
double ksi = el_par_value("ksi",el);
1119+
double lrad = el_par_value("lrad",el);
1120+
if(l>0) { // thick solenoid
1121+
if(ks==0 && ksi!=0) ks=ksi/l; // ks not specified, get ks from ksi
1122+
store_comm_par_value("ks",ks,el->def);
1123+
if(lrad!=0) warning(el->name," thick (l>0) solenoid with lrad, ignore lrad");
1124+
}
1125+
else { // thin solenoid
1126+
if(ks !=0 && ksi!=0 && lrad>0 && fabs(ks*lrad-ksi)>1.e-10) ks=0; // redudant inconsistent parameters. ignore ks, then get below from ksi/lrad
1127+
if(ksi!=0 && lrad>0 && ks==0) { // ks from ksi/lrad, used in thin solenoid subroutine tmsol_th
1128+
ks=ksi/lrad;
1129+
store_comm_par_value("ks",ks,el->def);
1130+
}
1131+
if(lrad==0 && ks!=0 && ksi!=0) { // lrad from ksi/ks
1132+
lrad=ksi/ks;
1133+
if(lrad<0) warning(el->name," lrad=ksi/ls<0");
1134+
store_comm_par_value("lrad",lrad,el->def);
1135+
}
1136+
}
1137+
if(l<=0 && lrad<=0) warning(el->name," solenoid should have positive l or lrad");
1138+
}

src/mad_elem.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ int is_custom_set(void);
101101
void update_node_aperture(void);
102102
void check_for_update_in_seq(struct element* el, struct command* update, int nupdates);
103103
int check_for_perm_misalign(struct node*, struct in_cmd* cmd);
104+
void check_set_consistent_solenoid(struct element *el, struct command* def);
104105
// used by mad_mkthin.c
105106
struct command_parameter* return_param(const char* par, const struct element*);
106107
struct command_parameter* return_param_recurse(const char* par, const struct element*);

src/mad_mkthin.cpp

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -892,7 +892,34 @@ static void force_consistent_slices(el_list* the_element_list) // hbu 10/2005 lo
892892
child->double_value=slices;
893893
parent->double_value=slices_parent;
894894
int el_thick_pos = name_list_pos("thick",nl);
895-
if(el_thick_pos > -1) el->parent->def->par->parameters[el_thick_pos]->double_value = el_def->par->parameters[el_thick_pos]->double_value; // copy thick flag from child to parent
895+
if(el_thick_pos > -1) el->parent->def->par->parameters[el_thick_pos]->double_value = el_def->par->parameters[el_thick_pos]->double_value; // copy slice number from child to parent
896+
}
897+
}
898+
}
899+
}
900+
901+
static void zero_length_elements_1_slice(el_list* the_element_list)
902+
// zero length elements will not be sliced
903+
// they can still get a slice number > 1 from select,flag=makethin which can be confusing, avoided here by assuring the default slice=1
904+
{
905+
for(int i=0; i< the_element_list->curr; ++i) // loop over the_element_list
906+
{
907+
element* el = the_element_list->elem[i];
908+
bool found;
909+
double el_length=my_get_int_or_double_value(el,"l",found);
910+
const command* el_def=el->def;
911+
name_list* nl=el_def->par_names;
912+
const int ei=name_list_pos("slice",nl);
913+
if(ei > -1 && el->parent!=nullptr && el != el->parent )
914+
{
915+
bool found_parent;
916+
double el_parent_length=my_get_int_or_double_value(el->parent,"l",found_parent);
917+
command_parameter* child=el_def->par->parameters[ei];
918+
command_parameter* parent=el->parent->def->par->parameters[ei];
919+
if(!found || fmax(el_length,el_parent_length)<1.e-10) // element and its parent have zero length, remove slice number
920+
{ // assure that zero length elements have the default slice=1
921+
child->double_value=1;
922+
parent->double_value=1;
896923
}
897924
}
898925
}
@@ -1282,13 +1309,13 @@ void makethin(in_cmd* incmd) // public interface to slice a sequence, called by
12821309
name_list* nl = incmd->clone->par_names;
12831310
command_parameter_list* pl = incmd->clone->par;
12841311

1285-
static std::string LastSequenceSliced,LastStyle="teapot";
1286-
static SequenceList sliced_seqlist;
1287-
12881312
MaTh::Verbose=0;
12891313
if(get_option("debug")) MaTh::Verbose=1;
12901314
if(get_option("verbose")) MaTh::Verbose=2;
12911315

1316+
static std::string LastSequenceSliced,LastStyle="teapot";
1317+
static SequenceList sliced_seqlist;
1318+
12921319
const int ipos_style = name_list_pos("style", nl);
12931320
std::string slice_style;
12941321

@@ -1344,7 +1371,7 @@ void makethin(in_cmd* incmd) // public interface to slice a sequence, called by
13441371
if (MaTh::Verbose&& iret) std::cout << "after set_selected_elements iret=" << iret << std::endl;
13451372
}
13461373
else warning("makethin: no selection list,","slicing all to one thin lens.");
1347-
1374+
zero_length_elements_1_slice(element_list);
13481375
if(iMakeConsistent) force_consistent_slices(element_list);
13491376

13501377
const int ipos_seq = name_list_pos("sequence", nl);
@@ -1375,7 +1402,7 @@ void makethin(in_cmd* incmd) // public interface to slice a sequence, called by
13751402
}
13761403

13771404
//-------- SliceDistPos
1378-
SliceDistPos::SliceDistPos(const int n,const bool teapot_fl) : delta(0.5), Delta(0),delta_str("1/2"),delta_half_str("1/4"),Delta_str("0"),Delta_half_str("0")
1405+
SliceDistPos::SliceDistPos(const int n,const bool teapot_fl) : delta(0.5), Delta(1),delta_str("1/2"),delta_half_str("1/4"),Delta_str("1"),Delta_half_str("0")
13791406
{ // typically called with slice_style==std::string("teapot") which is true for teapot and false for simple
13801407
// note that n = number of cuts = number of thin slices = number of thick slices -1
13811408
// called for thick slices, positions of thin slices are calculated with simple_at_shift teapot_at_shift
@@ -2116,14 +2143,12 @@ element* SeqElList::create_thin_solenoid(const element* thick_elem, int slice_no
21162143
const command_parameter* length_param = return_param_recurse("l",thick_elem);
21172144
const command_parameter* kns_param = return_param_recurse("ks",thick_elem);
21182145
command_parameter* ksi_par=par_scaled(kns_param,length_param,"ksi",nslices);
2119-
command* cmd = new_cmdptr( thick_elem );
2120-
copy_params_from_elem(cmd,thick_elem,str_v_join(MaTh::DoNotCopy,{"kill_ent_fringe","kill_exi_fringe"}));
2146+
command* cmd = new_cmdptr( find_element("solenoid", base_type_list) );
2147+
copy_params_from_elem(cmd,thick_elem,str_v_join(MaTh::DoNotCopy,{"l","kill_ent_fringe","kill_exi_fringe"}));
21212148
SetParameter_in_cmd(cmd,ksi_par,"ksi",1);
2122-
21232149
set_lrad(cmd,length_param,nslices); // keep l as lrad
21242150
if(verbose>1) std::cout << __FILE__ << " " << __PRETTY_FUNCTION__ << " line " << std::setw(4) << __LINE__ << " " << my_dump_command(cmd) << std::endl;
21252151
finish_make_sliced_elem(sliced_elem, thick_elem, cmd, parent_or_base, slice_no);
2126-
ParameterRemove("l",sliced_elem);
21272152
return sliced_elem;
21282153
}
21292154

@@ -2276,8 +2301,9 @@ void SeqElList::slice_node_translate() // slice/translate and add slices to slic
22762301
{
22772302
if(nslices==1) // single thick
22782303
{
2279-
en = thick_elem; // full slice as entry, no body/exit
2280-
if(verbose>1) std::cout << __FILE__ << " " << __PRETTY_FUNCTION__ << " line " << std::setw(4) << __LINE__ << " ThickSLice, nslices=" << nslices << " create thick slices _en, _bo, _ex thick_elem->name=" << thick_elem->name << " here single slice just entry, not body, exit" << '\n';
2304+
en = thick_elem; // full slice
2305+
if(verbose>1) std::cout << __FILE__ << " " << __PRETTY_FUNCTION__ << " line " << std::setw(4) << __LINE__ << " ThickSLice, nslices=" << nslices << " create single thick_elem->name=" << thick_elem->name << " single body between dipedges with fringe fields"<< '\n';
2306+
en = create_thick_slice(thick_elem,1);
22812307
}
22822308
else // nslices>1
22832309
{
@@ -2313,7 +2339,7 @@ void SeqElList::slice_node_translate() // slice/translate and add slices to slic
23132339

23142340
if(ThickSLice) // fill space between slices
23152341
{
2316-
if(i==1) place_thick_slice(thick_elem,en,i); // place entry slice
2342+
if(i==1) place_thick_slice(thick_elem,en,i); // place entry or single thick slice
23172343
else if(i<nslices) place_thick_slice(thick_elem,bo,i); // place body/middle slice
23182344
else place_thick_slice(thick_elem,ex,i); // place exit slice
23192345
// place exit body after loop
@@ -2506,7 +2532,7 @@ void SeqElList::finish_make_sliced_elem(element*& sliced_elem, const element* th
25062532
theSliceList->put_slice(thick_elem,sliced_elem);
25072533
}
25082534

2509-
node* SeqElList::copy_thin(node* work_node) // this copies an element node and sets the length to zero and lrad to the length to be used for "copying" optically neutral elements
2535+
node* SeqElList::copy_thin(node* work_node) // this copies an element node, when L>0 sets the length to zero and lrad to the length to be used for "copying" optically neutral elements
25102536
{
25112537
if ( MaTh::Verbose>1) std::cout << __FILE__ << " " << __PRETTY_FUNCTION__ << " line " << std::setw(4) << __LINE__ << " " << std::setw(MaTh::par_name_maxlen) << work_node->name << " " << std::setw(MaTh::el_type_maxlen) << work_node->base_name << " thin_node->length=" << work_node->length << " l=" << el_par_value("l",work_node->p_elem) << std::endl;
25122538
node* thin_node = nullptr;
@@ -2518,6 +2544,8 @@ node* SeqElList::copy_thin(node* work_node) // this copies an element node and s
25182544
}
25192545
thin_node->length=0;
25202546
thin_node->p_elem->length=0;
2547+
ParameterRemove("slice",thin_node->p_elem); // slicing done, no need to keep slice number
2548+
ParameterRemove("thick",thin_node->p_elem); // slicing done, no need to keep thick
25212549
return thin_node;
25222550
}
25232551

src/mad_node.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,11 @@ store_node_value(const char* par, double* value)
604604
else if (strcmp(lpar, "rm64") == 0) store_comm_par_value("rm64",*value,el->def);
605605
else if (strcmp(lpar, "rm65") == 0) store_comm_par_value("rm65",*value,el->def);
606606
else if (strcmp(lpar, "rm66") == 0) store_comm_par_value("rm66",*value,el->def);
607+
608+
/* added by hbu May 2023 for check_set_consistent_solenoid */
609+
else if (strcmp(lpar, "ks") == 0) store_comm_par_value("ks",*value,el->def);
610+
else if (strcmp(lpar, "lrad") == 0) store_comm_par_value("lrad",*value,el->def);
611+
607612
// This needs to be cleaned up.
608613

609614

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
amb := 0.01;
22
lmb := 10;
33
mb1_den: dipedge,h:=( amb ) / ( lmb ) ,entrance=true;
4-
mb1: sbend,l:=lmb ,angle:=amb ,thick=true,kill_ent_fringe=true,kill_exi_fringe=true;
4+
mb1_bo: sbend,l:=( lmb ) * ( 1 ) ,angle:=( amb ) * ( 1 ) ,thick=true,kill_ent_fringe=true,kill_exi_fringe=true;
55
mb1_dex: dipedge,h:=( amb ) / ( lmb ) ,entrance=false;
66
myseq: sequence, l = 30;
77
mb1_den, at = ( lmb / 2 ) + ( ( lmb ) * ( 0 - 0.5 ) ) ;
8-
mb1, at = ( lmb / 2 ) + ( ( lmb ) * ( 0 ) ) ;
8+
mb1_bo, at = ( lmb / 2 ) + ( ( lmb ) * ( 0 ) ) ;
99
mb1_dex, at = ( lmb / 2 ) + ( ( lmb ) * ( 0.5 ) ) ;
1010
mb1_den, at = ( 1.5 * lmb ) + ( ( lmb ) * ( 0 - 0.5 ) ) ;
11-
mb1, at = ( 1.5 * lmb ) + ( ( lmb ) * ( 0 ) ) ;
11+
mb1_bo, at = ( 1.5 * lmb ) + ( ( lmb ) * ( 0 ) ) ;
1212
mb1_dex, at = ( 1.5 * lmb ) + ( ( lmb ) * ( 0.5 ) ) ;
1313
endsequence;

0 commit comments

Comments
 (0)