Source code for analysis_modules.eigenmode.SLANS.slans_geom_par

import json
import os
import subprocess
from math import floor

from analysis_modules.eigenmode.SLANS.geometry_manual import Geometry
from analysis_modules.eigenmode.SLANS.slans_code import SLANS
import numpy as np

from utils.file_reader import FileReader
fr = FileReader()


[docs]class SLANSGeometry(Geometry): def __init__(self, win=None): if win: super().__init__(win) self.ui = win.ui
[docs] def cavity(self, no_of_cells=1, no_of_modules=1, mid_cells_par=None, l_end_cell_par=None, r_end_cell_par=None, fid=None, bc=33, f_shift='default', beta=1, n_modes=2, proc=0, beampipes=None, parentDir=None, projectDir=None): if os.path.exists(projectDir): os.chdir(projectDir) else: print("Folder does not exist.") self.fid = fid self.set_geom_parameters(no_of_cells, mid_cells_par, l_end_cell_par, r_end_cell_par, beampipes) # print(mid_cells_par, l_end_cell_par, self.left_beam_pipe, self.right_beam_pipe) self.slans = SLANS(self.left_beam_pipe, self.left_end_cell, self.mid_cell, self.right_end_cell, self.right_beam_pipe, self.Jxy_all, self.Jxy_all_bp) # create folder if fid != "_0": check = self.createFolder() n = no_of_cells # Number of cells axi_sym = 2 # 1: flat, 2:axisymmetric self.unit = 3 # 1:m, 2:cm, 3:mm, 4:mkm name_index = 1 sc = 1 end_type = 1 # if end_type = 1 the end HALF cell is changed for tuning. If end_type = 2 the WHOLE end cell is changed for tuning end_L = 1 # if end_L = 1 the type of end cell is type a (without iris) if end_L = 2 the type of end cell is type b end_R = 1 # Beam pipe length if end_L == 1: self.Rbp_L = self.ri_L if end_R == 1: self.Rbp_R = self.ri_R # Ellipse conjugate points x,y zr12_L, alpha_L = self.slans.rz_conjug('left') # zr12_R first column is z , second column is r zr12_R, alpha_R = self.slans.rz_conjug('right') # zr12_R first column is z , second column is r zr12_M, alpha_M = self.slans.rz_conjug('mid') # zr12_R first column is z , second column is r if end_L == 2: zr12_BPL, alpha_BPL = self.slans.rz_conjug('left') # zr12_R first column is z , second column is r if end_R == 2: zr12_BPR, alpha_BPR = self.slans.rz_conjug('right') # zr12_R first column is z , second column is r # Set boundary conditions BC_Left = floor(bc/10) # 1:inner contour, 2:Electric wall Et = 0, 3:Magnetic Wall En = 0, 4:Axis, 5:metal BC_Right = bc % 10 # 1:inner contour, 2:Electric wall Et = 0, 3:Magnetic Wall En = 0, 4:Axis, 5:metal filename = f'cavity_{bc}' # Write Slans Geometry # with open(f"{projectDir}/SimulationData/SLANS/{fid}/{filename}.geo", 'w') as f: with open(f"{projectDir}/SimulationData/SLANS/{fid}/{filename}.geo", 'w') as f: # print("it got here") # N1 Z R Alfa Mesh_thick Jx Jy BC_sign Vol_sign # print(n) # print(self.WG_mesh) f.write('8 {:.0f} {:.0f} 2 {}\n'.format( self.Jxy * n + self.Jxy_bp * ((1 if end_R == 2 else 0) / 2 + (1 if end_L == 2 else 0) / 2) + (1 if self.WG_L > 0 else 0) * self.WG_mesh + (1 if self.WG_R > 0 else 0) * self.WG_mesh, self.Jxy, self.unit)) f.write('10 0 0 0 0 0 0 0 0\n') f.write('1 0 {:g} 0 1 0 {:.0f} {:.0f} 0\n'.format(self.ri_L, self.Jy0, BC_Left)) if end_L == 2: f.write('1 0 {:g} 0 1 0 {:.0f} {:.0f} 0\n'.format(self.Rbp_L, self.Jxy_all_bp[5] + self.Jxy_all_bp[6] + self.Jxy_all_bp[7], BC_Left)) if self.WG_L > 0: if end_L == 2: f.write('1 {:g} {:g} 0 1 {:.0f} 0 5 0\n'.format(self.WG_L - self.x_L, self.Rbp_L, self.WG_mesh)) else: f.write('1 {:g} {:g} 0 1 {:.0f} 0 5 0\n'.format(self.WG_L, self.Rbp_L, self.WG_mesh)) # n == 1 if n == 1: if self.Req_L != self.Req_R: print('The equator radius of left and right cell are not equal') # if exist('L_M') != 1: # L_M = [] if end_L == 2: self.slans.slans_bp_L(n, zr12_BPL, self.WG_L, f) self.slans.slans_n1_L(n, zr12_L, self.WG_L, f) self.slans.slans_n1_R(n, zr12_R, self.WG_L, f) if end_R == 2: self.slans.slans_bp_R(n, zr12_BPR, self.WG_L, f) if self.WG_R > 0: if end_R == 2: f.write('1 {:g} {:g} 0 1 {:.0f} 0 5 0\n'.format(self.WG_L + self.WG_R + self.L_L + self.L_R, self.Rbp_R, self.WG_mesh)) else: f.write('1 {:g} {:g} 0 1 {:.0f} 0 5 0\n'.format(self.WG_L + self.WG_R + self.L_L + self.L_R, self.Rbp_R, self.WG_mesh)) if end_R == 2: f.write('1 {:g} {:g} 0 1 0 {:.0f} {:.0f} 0\n'.format(self.WG_L + self.WG_R + self.L_L + self.L_R, self.ri_R, -(self.Jxy_all_bp[5] + self.Jxy_all_bp[6] + self.Jxy_all_bp[7]), BC_Right)) f.write( '1 {:g} 0 0 1 0 {:.0f} {:.0f} 0\n'.format(self.WG_L + self.WG_R + self.L_L + self.L_R, -self.Jy0, BC_Right)) f.write('1 0 0 0 1 {:.0f} 0 4 0\n'.format(-(self.Jxy * n + self.Jxy_bp * ( (1 if end_R == 2 else 0) / 2 + (1 if end_L == 2 else 0) / 2) + (1 if self.WG_L > 0 else 0) * self.WG_mesh + (1 if self.WG_R > 0 else 0) * self.WG_mesh))) f.write('0 0 0 0 0 0 0 0 0') # n>1 if n > 1: if end_L == 2: self.slans.slans_bp_L(n, zr12_BPL, self.WG_L, f) self.slans.slans_n1_L(n, zr12_L, self.WG_L, f) for i in range(1, n): self.slans.slans_M(n, zr12_M, self.WG_L, f, i, end_type) self.slans.slans_n1_R(n, zr12_R, self.WG_L, f) if end_R == 2: self.slans.slans_bp_R(n, zr12_BPR, self.WG_L, f) if self.WG_R > 0: if end_R == 2: f.write('1 {:g} {:g} 0 1 {:.0f} 0 5 0\n'.format( self.WG_L + self.WG_R + self.L_L + self.L_R + 2 * (n - 1) * self.L_M, self.Rbp_R, self.WG_mesh)) else: f.write('1 {:g} {:g} 0 1 {:.0f} 0 5 0\n'.format( self.WG_L + self.WG_R + self.L_L + self.L_R + 2 * (n - 1) * self.L_M, self.Rbp_R, self.WG_mesh)) if end_R == 2: f.write('1 {:g} {:g} 0 1 0 {:.0f} {:.0f} 0\n'.format( self.WG_L + self.WG_R + self.L_L + self.L_R + 2 * (n - 1) * self.L_M, self.ri_R, -(self.Jxy_all_bp[5] + self.Jxy_all_bp[6] + self.Jxy_all_bp[7]), BC_Right)) f.write('1 {:g} 0 0 1 0 {:.0f} {:.0f} 0\n'.format( self.WG_L + self.WG_R + self.L_L + self.L_R + 2 * (n - 1) * self.L_M, -self.Jy0, BC_Right)) # # gradual mesh decrease # if self.WG_R > 0: # f.write('1 {:g} 0 0 1 {:.0f} 0 4 0\n'.format(self.WG_L + self.L_L + self.L_R + 2 * (n - 1) * self.L_M, # -((1 if self.WG_R > 0 else 0) * self.WG_mesh))) # # f.write('1 {:g} 0 0 1 {:.0f} 0 4 0\n'.format(self.WG_L + self.L_L + 2 * (n - 1) * self.L_M - self.L_M, # -(self.Jxy * 1))) # # for i in range(n - 1, 1, -1): # f.write('1 {:g} 0 0 1 {:.0f} 0 4 0\n'.format(self.WG_L + self.L_L + 2 * (i - 1) * self.L_M - self.L_M, # -(self.Jxy * 1))) # # f.write('1 {:g} 0 0 1 {:.0f} 0 4 0\n'.format(self.WG_L, -(self.Jxy * 1))) # # if self.WG_L > 0: # f.write('1 {:g} 0 0 1 {:.0f} 0 4 0\n'.format(0, -((1 if self.WG_L > 0 else 0) * self.WG_mesh))) # direct mesh decrease f.write('1 0 0 0 1 {:.0f} 0 4 0\n'.format(-(self.Jxy*n + self.Jxy_bp * ((1 if end_R == 2 else 0)/2 + (1 if end_L == 2 else 0)/2) + (1 if self.WG_L > 0 else 0)*self.WG_mesh +(1 if self.WG_R > 0 else 0)*self.WG_mesh))) f.write('0 0 0 0 0 0 0 0 0') # Slans run genmesh_path = fr'{parentDir}\exe\SLANS_exe\genmesh2.exe' # filepath = fr'{projectDir}\SimulationData\SLANS\{fid}\{filename}' filepath = fr'{projectDir}\SimulationData\SLANS\{fid}\{filename}' # folder for exe to write to # cwd = fr'{projectDir}\SimulationData\SLANS\{fid}' cwd = fr'{projectDir}\SimulationData\SLANS\{fid}' # the next two lines suppress pop up windows from the slans codes # the slans codes, however, still disrupts windows operation, sadly. This is the case even for the slans tuner startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW subprocess.call([genmesh_path, filepath, '-b'], cwd=cwd, startupinfo=startupinfo) # path = fr'{projectDir}\SimulationData\SLANS\Cavity{self.fid}' path = fr'{projectDir}\SimulationData\SLANS\{self.fid}' beta, f_shift, n_modes = 1, 0, no_of_cells + 1 self.write_dtr(path, filename, beta, f_shift, n_modes) slansc_path = fr'{parentDir}\exe\SLANS_exe\slansc' slansm_path = fr'{parentDir}\exe\SLANS_exe\slansm' slanss_path = fr'{parentDir}\exe\SLANS_exe\slanss' slansre_path = fr'{parentDir}\exe\SLANS_exe\slansre' # check if corresponding file exists at before the executable is called if os.path.exists(fr'{projectDir}\SimulationData\SLANS\{fid}\{filename}.geo'): subprocess.call([slansc_path, '{}'.format(filepath), '-b'], cwd=cwd, startupinfo=startupinfo) # settings, number of modes, etc if os.path.exists(fr'{projectDir}\SimulationData\SLANS\{fid}\{filename}.gem'): subprocess.call([slansm_path, '{}'.format(filepath), '-b'], cwd=cwd, startupinfo=startupinfo) if os.path.exists(fr'{projectDir}\SimulationData\SLANS\{fid}\aslans.mtx') \ and os.path.exists(fr'{projectDir}\SimulationData\SLANS\{fid}\bslans.mtx'): subprocess.call([slanss_path, '{}'.format(filepath), '-b'], cwd=cwd, startupinfo=startupinfo) if os.path.exists(fr'{projectDir}\SimulationData\SLANS\{fid}\{filename}.res'): subprocess.call([slansre_path, '{}'.format(filepath), '-b'], cwd=cwd, startupinfo=startupinfo) run_save_directory = f"{projectDir}/SimulationData/SLANS/{fid}" # save json file shape = {'IC': mid_cells_par, 'OC': l_end_cell_par, 'OC_R': r_end_cell_par} with open(f"{run_save_directory}/geometric_parameters.json", 'w') as f: json.dump(shape, f, indent=4, separators=(',', ': ')) try: filename = fr'{run_save_directory}/cavity_33.svl' d = fr.svl_reader(filename) Req = d['CAVITY RADIUS'][no_of_cells - 1] * 10 # convert to mm Freq = d['FREQUENCY'][no_of_cells - 1] E_stored = d['STORED ENERGY'][no_of_cells - 1] Rsh = d['SHUNT IMPEDANCE'][no_of_cells - 1] # MOhm Q = d['QUALITY FACTOR'][no_of_cells - 1] Epk = d['MAXIMUM ELEC. FIELD'][no_of_cells - 1] # MV/m Hpk = d['MAXIMUM MAG. FIELD'][no_of_cells - 1] # A/m # Vacc = dict['ACCELERATION'][no_of_cells - 1] Eavg = d['AVERAGE E.FIELD ON AXIS'][no_of_cells - 1] # MV/m r_Q = d['EFFECTIVE IMPEDANCE'][no_of_cells - 1] # Ohm G = 0.00948 * Q * (Freq / 1300) GR_Q = G * 2 * r_Q Vacc = np.sqrt( 2 * r_Q * E_stored * 2 * np.pi * Freq * 1e6) * 1e-6 # factor of 2, remember circuit and accelerator definition # Eacc = Vacc / (374 * 1e-3) # factor of 2, remember circuit and accelerator definition norm_length = 2*mid_cells_par[5] Eacc = Vacc / ( no_of_cells * norm_length * 1e-3) # for 1 cell factor of 2, remember circuit and accelerator definition Epk_Eacc = Epk / Eacc Bpk = (Hpk * 4 * np.pi * 1e-7) * 1e3 Bpk_Eacc = Bpk / Eacc d = { "Req": Req, "Normalization Length": norm_length, "freq": Freq, "Q": Q, "E": E_stored, "Vacc": Vacc, "Eacc": Eacc, "Epk": Epk, "Hpk": Hpk, "Bpk": Bpk, "R/Q": 2 * r_Q, "Epk/Eacc": Epk_Eacc, "Bpk/Eacc": Bpk_Eacc, "G": G, "GR/Q": GR_Q } with open(fr'{run_save_directory}\qois.json', "w") as f: json.dump(d, f, indent=4, separators=(',', ': ')) except FileNotFoundError: print("Simulation failed")
[docs] def write_dtr(self, path, filename, beta, f_shift, n_modes): with open("{}\{}.dtr".format(path, filename), 'w') as f: f.write(': Date:02/04/16 \n') f.write('{:g} :number of iterative modes 1-10\n'.format(n_modes)) f.write('{:g} :number of search modes\n'.format(n_modes - 1)) f.write('9.99999997E-007 :convergence accuracy\n') f.write('50 :maximum number of iterations\n') f.write('0 :continue iterations or not 1,0\n') f.write(' {:g}. :initial frequency shift MHz\n'.format(f_shift)) f.write('1 :wave type 1-E, 2-H\n') f.write(' 1 :struct. 1-cav,2-per.str,3-w.guid.,4-l.-hom.\n') f.write('0 :symmetry yes or not 1,0\n') f.write(' 1 :number of met.surfaces, then:sign and sigma\n') f.write('5 1.\n') f.write('0 : number of mark volumes,then:sign,EPS,MU,TGE,TGM\n') f.write('{:g} : beta (v/c)\n'.format(beta))
[docs] def createFolder(self): path = os.getcwd() path = os.path.join(path, f"SimulationData/SLANS/{self.fid}") if os.path.exists(path): pass else: os.mkdir(path) return "Yes"