import time
from analysis_modules.tune.tuners.pyTuner import PyTune
from analysis_modules.eigenmode.SLANS.slansTuner import SLANSTune
from utils.shared_classes import *
from utils.shared_functions import *
from utils.file_reader import FileReader
from analysis_modules.eigenmode.SLANS.slans_geom_par import SLANSGeometry
fr = FileReader()
slans_geom = SLANSGeometry()
[docs]class Tuner:
def __init__(self):
pass
[docs] def tune(self, pseudo_shape_space, bc, parentDir, projectDir, filename, resume="No",
proc=0, tuner_option='SLANS', tune_variable='Req', iter_set=None, cell_type='Mid Cell',
progress_list=None, convergence_list=None, save_last=True, n_cell_last_run=1):
# tuner
pytune = PyTune()
if tuner_option == 'SLANS':
slans_tune = SLANSTune(parentDir, projectDir)
else:
slans_tune = None
start = time.time()
population = {}
total_no_of_shapes = len(list(pseudo_shape_space.keys()))
# check for already processed shapes
existing_keys = []
if resume == "Yes":
# check if value set is already written. This is to enable continuation in case of break in program
if os.path.exists(fr'{projectDir}/Cavities/{filename}'):
population = json.load(open(fr'{projectDir}/Cavities/{filename}', 'r'))
existing_keys = list(population.keys())
# print(f'Existing keys: {existing_keys}')
progress = 0
error_msg1 = 1
error_msg2 = 1
for key, pseudo_shape in pseudo_shape_space.items():
# print(pseudo_shape['IC'])
A_i, B_i, a_i, b_i, Ri_i, L_i, Req, _, _ = pseudo_shape['IC'] # Req here is none but required
# since the shape space consists of all variables
A_o, B_o, a_o, b_o, Ri_o, L_o, Req_o, _, _ = pseudo_shape['OC'] # Req here is none but required
# since the shape space consists of all variables
beampipes = pseudo_shape['BP']
target_freq = pseudo_shape['FREQ']
# Check if simulation is already run
freq = 0
alpha_i = 0
alpha_o = 0
if resume == "Yes" and os.path.exists(fr'{projectDir}/SimulationData/SLANS/{key}'):
# if folder exist, read value
filename = fr'{projectDir}/SimulationData/SLANS/{key}/cavity_{bc}.svl'
try:
data_dict = fr.svl_reader(filename)
# print(data_dict)
if tune_variable == 'Req':
Req = data_dict['CAVITY RADIUS'][0]*10
freq = data_dict['FREQUENCY'][0]
else:
L = data_dict['LENGTH'][0]*10
freq = data_dict['FREQUENCY'][0]
if cell_type == 'Mid Cell':
L_i, L_o = L, L
else:
L_o = L
except FileNotFoundError:
if tune_variable == 'Req':
Req = 0
freq = 0
else:
L = 0
freq = 0
if cell_type == 'Mid Cell':
L_i, L_o = L, L
else:
L_o = L
alpha_i, error_msg1 = calculate_alpha(A_i, B_i, a_i, b_i, Ri_i, L_i, Req, 0)
alpha_o, error_msg2 = calculate_alpha(A_o, B_o, a_o, b_o, Ri_o, L_o, Req, 0)
inner_cell = [A_i, B_i, a_i, b_i, Ri_i, L_i, Req, alpha_i]
outer_cell = [A_o, B_o, a_o, b_o, Ri_o, L_o, Req, alpha_o]
else:
# new mid cell and end cell with initial Req guess
if cell_type == 'End Cell': # change later for two types of end cells,
# one with half mid cell and the other with same dimensions
Req_o = Req
if cell_type == 'End-End Cell':
if Req < Ri_i + B_i + b_i or Req < Ri_o + B_o + b_o:
Req = Ri_i + B_i + b_i
Req_o = Req
inner_cell = [A_i, B_i, a_i, b_i, Ri_i, L_i, Req, 0]
outer_cell = [A_o, B_o, a_o, b_o, Ri_o, L_o, Req_o, 0]
# edit to check for key later
if key not in existing_keys:
if tuner_option == 'SLANS' and slans_tune:
if tune_variable == 'Req':
# Tune cell to get Req
Req, freq, alpha, h, e = slans_tune.mid_cell_tune(A_i, B_i, a_i, b_i, Ri_i, L_i, Req,
target_freq, proc=proc)
else:
L, freq, alpha, h, e = slans_tune.end_cell_tune(inner_cell, outer_cell,
target_freq, proc=proc)
if cell_type == 'Mid Cell':
L_i, L_o = L, L
else:
L_o = L
inner_cell = [A_i, B_i, a_i, b_i, Ri_i, L_i, Req, alpha]
outer_cell = [A_o, B_o, a_o, b_o, Ri_o, L_o, Req, alpha]
else:
if tune_variable == 'Req':
try:
Req, freq = pytune.tuneR(inner_cell, outer_cell, target_freq, beampipes, bc,
parentDir, projectDir, iter_set=iter_set, proc=proc,
conv_list=convergence_list)
except FileNotFoundError:
Req, freq = 0, 0
# round
Req, freq = Req, freq
else:
try:
L, freq = pytune.tuneL(inner_cell, outer_cell, target_freq, beampipes, bc,
parentDir, projectDir, iter_set=iter_set, proc=proc,
conv_list=convergence_list)
except FileNotFoundError:
L, freq = 0, 0
if cell_type == 'Mid Cell':
L_i, L_o = L, L
else:
L_o = L
if Req == 0 or L_i == 0 or L_o == 0:
alpha_i = 0
alpha_o = 0
else:
alpha_i, error_msg1 = calculate_alpha(A_i, B_i, a_i, b_i, Ri_i, L_i, Req, 0)
alpha_o, error_msg2 = calculate_alpha(A_o, B_o, a_o, b_o, Ri_o, L_o, Req, 0)
inner_cell = [A_i, B_i, a_i, b_i, Ri_i, L_i, Req, alpha_i]
outer_cell = [A_o, B_o, a_o, b_o, Ri_o, L_o, Req, alpha_o]
result = "Failed"
# # round
# L, freq = round(L, 2), round(freq, 2)
if (1 - 0.001)*target_freq < round(freq, 2) < (1 + 0.001)*target_freq \
and (90.0 <= alpha_i <= 180) \
and (90.0 <= alpha_o <= 180) and error_msg1 == 1 and error_msg2 == 1:
result = f"Success: {target_freq, freq}"
if cell_type == 'Mid Cell':
population[key] = {"IC": inner_cell, "OC": outer_cell, "BP": 'none', 'FREQ': freq}
else:
population[key] = {"IC": inner_cell, "OC": outer_cell, "BP": 'both', 'FREQ': freq}
# save last slans run if activated. Save only when condition is fulfilled
if save_last:
# self.save_last(projectDir, proc, key)
# print("n_cell tuner", n_cell_last_run)
if 'End' in cell_type:
beampipes = 'both'
slans_geom.cavity(n_cell_last_run, 1, inner_cell, outer_cell, outer_cell, f_shift=0, bc=bc,
beampipes=beampipes, proc=proc,
n_modes=n_cell_last_run+1, fid=key, parentDir=parentDir, projectDir=projectDir)
# write cst_studio parameters
write_cst_paramters(key, inner_cell, outer_cell, projectDir, cell_type)
# write tune results
if cell_type == 'Mid Cell':
d_tune_res = {'Req': Req, 'L': L_i, 'alpha_i': alpha_i, 'alpha_o': alpha_o, 'freq': freq}
else:
d_tune_res = {'Req': Req, 'L': L_o, 'alpha_i': alpha_i, 'alpha_o': alpha_o, 'freq': freq}
self.save_tune_result(d_tune_res, projectDir, key)
print(f'Done Tuning Cavity {key}: {result}')
# clear folder after every run. This is to avoid copying of wrong values to save folder
# processor folder
proc_fold = fr'{projectDir}/SimulationData/SLANS/_process_{proc}'
keep = ['SLANS_exe']
for item in os.listdir(proc_fold):
if item not in keep: # If it isn't in the list for retaining
try:
os.remove(item)
except FileNotFoundError:
continue
# update progress
progress_list.append((progress + 1) / total_no_of_shapes)
# Update progressbar
progress += 1
# print("Saving Dictionary", f"shape_space{proc}.json")◙
# print("Done saving")
end = time.time()
runtime = end - start
print(f'Processor {proc} runtime: {runtime}')
[docs] @staticmethod
def save_tune_result(d, projectDir, key):
with open(fr"{projectDir}\SimulationData\SLANS\{key}\tune_res.json", 'w') as file:
file.write(json.dumps(d, indent=4, separators=(',', ': ')))
# if __name__ == '__main__':
# #
# tune = Tuner()
#
# tune_var =
# par_mid =
# par_end =
# target_freq = 400 # MHz
# beampipes =
# bc = # boundary conditions
# parentDir = "" # location of slans code. See folder structure in the function above
# projectDir = "" # location to write results to
# iter_set =
# proc = 0
# tune.tune(self, tune_var, par_mid, par_end, target_freq, beampipes, bc, parentDir, projectDir, iter_set, proc=0):