!------------------------------------------------------------------------ !------------------------------------------------------------------------ !------------------------------------------------------------------------ subroutine change_var (line, do_all_universe, u) use cesrv_struct use cesrv_interface use super_universe_com use bookkeeper_mod implicit none type (var_struct), pointer :: this_var type (universe_struct), target :: u type (universe_struct), pointer :: uu type (ele_struct), pointer :: ele, ele2 type (all_pointer_struct) a_ptr character(*) line character(80) fmt, equation character(40) slave_name character(32) var_name integer i, ix, loc, ix_str integer :: change, delta$ = 1, absolute$ = 2, rel_design$ = 3 integer :: percent$ = 4 integer :: units, cu_now, cu_new, ix_attrib integer ix_con, ix_slave, ix_att, n_slave, ios real(rp) del, scale, merit0, merit1, now, design, dv_dcu, max_del logical :: err_flag, do_all_universe, vary_coef, doit = .false. !----------------------------------------------------------------- ! change element attribute? call string_trim (line, line, ix_str) if (index('ELEMENT', line(:ix_str)) == 1) then call string_trim (line(ix_str+1:), line, ix_str) call locate_element (u%ring, line, loc, err_flag) if (err_flag) return ele => u%ring%ele(loc) call string_trim (line(ix_str+1:), line, ix_str) if (ix_str == 0) then print *, 'ERROR: ELEMENT ATTRIBUTE NOT GIVEN' return endif ! for overlay_lord slaves if ('SLAVE' == line(1:ix_str)) then call string_trim(line(ix_str+1:), line, ix_str) read (line, *, iostat = ios) n_slave if (ix_str == 0 .or. ios /= 0) then print *, 'ERROR: SLAVE NUMBER NOT GIVEN' return endif if (n_slave < 1 .or. n_slave > ele%n_slave) then print *, 'ERROR: SLAVE NUMBER OUT OF RANGE' return endif ix_con = ele%ix1_slave + n_slave - 1 ix_slave = u%ring%control(ix_con)%slave%ix_ele slave_name = u%ring%ele(ix_slave)%name call string_trim(line(ix_str+1:), line, ix_str) if (index('NAME', line(1:ix_str)) == 1) then print *, 'ERROR: NAME NOT YET IMPLEMENTED CORRECTLY!' call err_exit call string_trim(line(ix_str+1:), line, ix_str) do loc = 1, u%ring%n_ele_max if (u%ring%ele(loc)%name == line(:ix_str)) then u%ring%control(ix_con)%slave%ix_ele = loc print *, 'Changed slave from ', trim(slave_name), ' to ', trim(u%ring%ele(loc)%name) return endif enddo print *, 'ERROR: CANNOT MATCH SLAVE NAME: ', line(:ix_str) print *, ' WITH RING ELEMENT' return elseif (index('ATTRIBUTE', line(1:ix_str)) == 1) then call string_trim(line(ix_str+1:), line, ix_str) ix_att = attribute_index(u%ring%ele(ix_slave), line(:ix_str)) if (ix_att == 0) then print *, 'ERROR: BAD ATTRIBUTE FOR SLAVE ELEMENT: ', line(:ix_str) return endif u%ring%control(ix_con)%ix_attrib = ix_att print *, 'Changed slave Attribute of slave ', trim(slave_name), & ' to ', attribute_name(u%ring%ele(ix_slave), ix_att) if (do_all_universe) then do i = 1, logic%u_num super%u_(i)%ring%control(ix_con)%ix_attrib = ix_att enddo endif return elseif (index('COEFFICIENT', line(1:ix_str)) == 1) then nullify(a_ptr%i); nullify(a_ptr%l) a_ptr%r => null() ! u%ring%control(ix_con)%coef call err_exit var_name = 'COEFFICIENT OF SLAVE ' // trim(u%ring%ele(ix_slave)%name) vary_coef = .true. else print *, 'ERROR: I DO NOT UNDERSTAND THIS: ', line(1:ix_str) return endif ! not an overlay slave change else call pointer_to_attribute (u%ring%ele(loc), line(:ix_str), .true., a_ptr, err_flag, .true.) if (err_flag .or. .not. (associated(a_ptr%r) .or. associated(a_ptr%i) .or. associated(a_ptr%l))) return if (.not. attribute_free (loc, line(:ix_str), u%ring, .true.)) return if (err_flag) return var_name = line(:ix_str) vary_coef = .false. endif ! Changing logical if (associated(a_ptr%l)) then var_name = line(:ix_str) call string_trim (line(ix_str+1:), line, ix_str) if (ix_str == 0) then a_ptr%l = .not. a_ptr%l elseif (line(1:1) == 'T') then a_ptr%l = .true. elseif (line(1:1) == 'F') then a_ptr%l = .false. else print *, 'ERROR: NEED TO SET THIS LOGICAL TO "TRUE" or "FALSE"' return endif call set_flags_for_changed_attribute (u%ring%ele(loc), a_ptr%l) print *, trim(ele%name), ' ', trim(var_name), ': ', a_ptr%l return endif ! Changing integer if (associated(a_ptr%i)) then equation = line(:ix_str) // ' = ' // line(ix_str+1:) call set_ele_attribute (u%ring%ele(loc), equation, u%ring, err_flag) call set_flags_for_changed_attribute (u%ring%ele(loc), a_ptr%i) print *, trim(ele%name), ': ', trim(equation) return endif ! now put in element change call string_trim (line(ix_str+1:), line, ix_str) call read_var_change (.false.) if (err_flag) return call merit_calc(merit0) now = a_ptr%r if (change == absolute$) del = del - now if (change == percent$) del = del * now / 100 a_ptr%r = now + del call set_flags_for_changed_attribute (u%ring%ele(loc), a_ptr%r) call lat_make_mat6 (u%ring, loc, u%orb) if (do_all_universe) then do i = 1, logic%u_num uu => super%u_(i) if (vary_coef) then call err_exit !! uu%ring%control(ix_con)%coef = a_ptr%r else uu%ring%ele(loc)%value(ix_attrib) = a_ptr%r call set_flags_for_changed_attribute (uu%ring%ele(loc), uu%ring%ele(loc)%value(ix_attrib)) call lat_make_mat6 (uu%ring, loc, uu%orb) endif enddo endif call merit_calc(merit1) if (do_all_universe) then print *, "Changing: ", ele%name, ' ', trim(var_name), " for all universes." elseif (logic%u_num .gt. 1) then print '(1x,5a,i3)', "Changing: ", ele%name, ' ', trim(var_name), & " for universe: ", logic%u_view else print *, ele%name, ' ', var_name endif if (max(abs(now), abs(del)) > 100) then fmt = '(10x, 2(a, f11.0))' else fmt = '(10x, 2(a, f11.6))' endif print fmt, 'Change in Value: ', now, ' ->', now+del if (del /= 0) then print *, ' Merit0, Merit1:', merit0, merit1 print *, ' dMerit/dValue: ', (merit1 - merit0) / del else print *, ' Merit:', merit0 endif return endif !----------------------------------------------------------------- ! change Twiss parameter? (used with the CUT_RING command) if (index('TWISS', line(:ix_str)) == 1) then print *, 'ERROR: CHANGE TWISS NOT YET IMPLEMENTED!' return endif !----------------------------------------------------------------- ! "normal" (not an element attribute) change ! find out which variable to change call match_var_name (line, this_var, ix, u, err_flag) if (err_flag) return if (.not. this_var%exists) then print *, 'ERROR: THIS VARIABLE DOES NOT EXIST!' return endif call read_var_change (.true.) if (err_flag) return call merit_calc(merit0) now = this_var%model design = this_var%design ! compute the change if (units == cu_units$) then if (this_var%dvar_dcu == 0) then print *, 'ERROR: DVAR_DCU (CHANGE IN STRENGTH/CHANGE IN CU) IS ZERO!' return endif del = del * this_var%dvar_dcu endif if (change == percent$) then if (units == cu_units$) then cu_now = nint((now - this_var%base_cu0) / this_var%dvar_dcu) del = del * cu_now / 100 else del = del * now / 100 endif endif if (change == absolute$) then del = del - now if (units == cu_units$) then del = del + this_var%base_cu0 endif elseif (change == rel_design$) then del = del + design - now endif ! is the change to large? max_del = 1 if (this_var%v1%type == sex_k2$) then max_del = 10 elseif (this_var%v1%type == custom_var$) then max_del = 100000 elseif (this_var%v1%type == skew_sex_k2$) then max_del = 10 elseif (this_var%v1%type == oct_k3$) then max_del = 1000 elseif (this_var%v1%type == db_group$) then max_del = 100000 elseif (this_var%v1%type == init_orb$) then max_del = 0.1 elseif (this_var%v1%type == skew_sex_k2$) then max_del = 100 endif if (abs(del) > max_del) then print *, 'This change is rather large...' doit = .false. call cesrv_logic_get ('Y', 'N', 'Shall I make the change?', doit) if (.not. doit) then print *, 'No change made.' return endif endif ! make the change if (max(abs(now), abs(design), abs(del)) > 100) then fmt = '(5x, 2(a, f11.0), 6x, a, f11.0)' else fmt = '(5x, 2(a, f11.6), 6x, a, f11.6)' endif if (do_all_universe) then print *, "Changing: ", this_var%name, " for all universes", & '; "', trim(this_var%db_ele_name), '"' elseif (logic%u_num .gt. 1) then print *, "Changing: ", this_var%name, " for universe: ", & logic%u_view, '; "', trim(this_var%db_ele_name), '"' else print *, this_var%name, ' "', trim(this_var%db_ele_name), '"' endif print fmt, 'Change in Value: ', now, ' ->', now+del, 'Del =', del if (design /= 0) print fmt, 'Relative to Design:', & now-design, ' ->', now+del-design, 'Del =', del dv_dcu = this_var%dvar_dcu if (dv_dcu /= 0) then cu_now = nint((now - this_var%base_cu0) / dv_dcu) cu_new = nint((now + del - this_var%base_cu0) / dv_dcu) print '(5x, 2(a, i11), 6x, a, i11)', 'Change in CU: ', & cu_now, ' ->', cu_new, 'Del =', cu_new-cu_now endif this_var%model = dble(now + del) call var_bookkeeper(this_var, u%ring, u%orb) if (do_all_universe) then ix = this_var%v1%ix_var + this_var%ix_index do i = 1, logic%u_num super%u_(i)%var(ix)%model = this_var%model call var_bookkeeper(super%u_(i)%var(ix), super%u_(i)%ring, super%u_(i)%orb) enddo endif if (del /= 0) then call merit_calc(merit1) print *, ' Merit, dMerit/dValue:', merit1, (merit1 - merit0) / del else print *, ' Merit:', merit0 endif !--------------------------------------------------------------------------- contains subroutine read_var_change (read_t_cu) logical read_t_cu err_flag = .false. change = delta$ scale = 1 ix = index(line, '@') if (ix /= 0) then change = absolute$ line (ix:ix) = ' ' endif ix = index(line, '%') if (ix /= 0) then change = percent$ line (ix:ix) = ' ' endif ix = index(line, 'D') if (ix /= 0) then scale = pi / 180 line (ix:ix) = ' ' endif ix = index(line, 'MM') if (ix /= 0) then scale = 1e-3 line(ix:ix+1) = ' ' endif ix = index(line, 'UM') if (ix /= 0) then scale = 1e-6 line(ix:ix+1) = ' ' endif ! if (read_t_cu) then ix = index(line, 'T') if (ix /= 0) then change = rel_design$ line (ix:ix) = ' ' endif ix = index(line, 'CU') if (ix /= 0) then units = cu_units$ line (ix:ix+1) = ' ' else units = bmad_units$ endif endif read (line, *, err = 9200, end = 9200) del del = del * scale call string_trim (line(ix_str+1:), line, ix_str) return ! 9200 print * print *, 'ERROR: BAD CHANGE NUMBER. NOTHING DONE.' err_flag = .true. end subroutine end subroutine