def run(args): if args.show_config: print(Config()) return if args.generate_config: abstract.dump(Config(), args.generate_config) return if args.file: if args.config: cfg = Config(**abstract.load(args.config)) else: cfg = Config() return main(cfg, args)
frac, _ = dblquad(load_func_psi_eta, 0, 1, 0, lambda x: 1 - x, epsrel=1e-1, epsabs=1e-1) da = ((xj - xi) * (yk - yi) - (xk - xi) * (yj - yi)) f[tri] += 1 / 6 * frac * da f[on_boundary] = 0 return f array_file = 'circular_mem_54.json' db_file = 'circular_mem_54.db' t_start = 0 t_stop = 6e-6 atol = 1e-10 array = abstract.load(array_file) patches = abstract.get_patches_from_array(array) mem = array.elements[0].membranes[0] amesh = mesh.Mesh.from_abstract(array, refn=7) nodes = amesh.vertices f = np.zeros((len(amesh.vertices), len(patches))) for i, pat in enumerate(patches): f[:,i] = circular_patch_f_vector(amesh.vertices, amesh.triangles, amesh.on_boundary, pat.position[0] - mem.position[0], pat.position[1] - mem.position[1], pat.radius_min, pat.radius_max, pat.theta_min, pat.theta_max) f[amesh.on_boundary,i] = 0 mask = f > 0
uavg = [] fpp = [] for di in d: ubar = (unorm * g * di).dot(avg) / pat.area uavg.append(ubar) fc.append((-e_0 / 2 / (unorm * g * di + g_eff)**2).dot(avg) / pat.area) fpp.append(-e_0 / 2 / (ubar + g_eff)**2) fcorr.append((d, unorm, uavg, fc, fpp)) # fcorr.append(interp1d(uavg, fc, kind='cubic', bounds_error=False, fill_value=(fc[-1], fc[0]))) return fcorr array = abstract.load('circular_membrane.json') fcorr = calc_es_correction(array, refn=9) from matplotlib import pyplot as plt for i in [0, 4, 8]: d, unorm, uavg, fc, fpp = fcorr[i] fig, ax = plt.subplots() ax.plot(uavg, fc) ax.plot(uavg, fpp, '--') fig.show()
def process(job): '''''' job_id, (f, k) = job # get options and parameters c = cfg.sound_speed rho = cfg.fluid_rho array = abstract.load(cfg.array_config) refn = cfg.mesh_refn # create finite element matrix Gfe, _ = fem.mbk_from_abstract(array, f, refn) # create boundary element matrix hmkwrds = [ 'aprx', 'basis', 'admis', 'eta', 'eps', 'm', 'clf', 'eps_aca', 'rk', 'q_reg', 'q_sing', 'strict' ] hmargs = {k: getattr(cfg, k) for k in hmkwrds} Z = bem.z_from_abstract(array, k, refn, format='HFormat', **hmargs) omg = 2 * np.pi * f Gbe = -omg**2 * 2 * rho * Z # define total linear system and preconditioner G = MbkSparseMatrix(Gfe) + Gbe Glu = G.lu() # create patch pressure load F = fem.f_from_abstract(array, refn) mesh = Mesh.from_abstract(array, refn) ob = mesh.on_boundary # solve for each source patch npatch = abstract.get_patch_count(array) source_patch = np.arange(npatch) dest_patch = np.arange(npatch) patches = abstract.get_patches_from_array(array) for sid in source_patch: # get RHS b = np.array(F[:, sid].todense()) # b[ob] = 0 # solve start = timer() # conjugate so phase is consistent with -iwt convention used by h2lib x = np.conj(Glu.lusolve(b)) time_solve = timer() - start x[ob] = 0 # average displacement over patches area = patches[sid].length_x * patches[sid].length_y # x_patch = (Pavg.T).dot(x) # / patch area? x_patch = (F.T).dot(x) / area # write results to database data = {} data['frequency'] = repeat(f) data['wavenumber'] = repeat(k) data['source_patch'] = repeat(sid) data['dest_patch'] = dest_patch data['displacement_real'] = np.real(x_patch) data['displacement_imag'] = np.imag(x_patch) data['time_solve'] = repeat(time_solve) with write_lock: update_db(file, **data) with write_lock: util.update_progress(file, job_id)
def process(job): ''' Process which executes a job. ''' job_id, (f, k) = job # get options and parameters c = cfg.sound_speed rho = cfg.fluid_rho array = abstract.load(cfg.array_config) refn = cfg.mesh_refn use_fluid = cfg.use_fluid # create boundary element matrix if use_fluid: # create finite element matrix Gfe = fem.array_mbk_spmatrix(array, refn, f, format='csr') hmkwrds = [ 'format', 'aprx', 'basis', 'admis', 'eta', 'eps', 'm', 'clf', 'eps_aca', 'rk', 'q_reg', 'q_sing', 'strict' ] hmargs = {k: getattr(cfg, k) for k in hmkwrds} # Z = bem.z_from_abstract(array, k, refn, format='HFormat', **hmargs) Z = bem.array_z_matrix(array, refn, k, **hmargs) omg = 2 * np.pi * f Gbe = -omg**2 * 2 * rho * Z # define total linear system and find LU decomposition G = MbkSparseMatrix(Gfe) + Gbe Glu = G.lu() else: # create finite element matrix Gfe = fem.array_mbk_spmatrix(array, refn, f, format='csc') # define total linear system and find LU decomposition Glu = splu(Gfe) # create patch pressure loads F = fem.array_f_spmatrix(array, refn) AVG = fem.array_avg_spmatrix(array, refn) mesh = Mesh.from_abstract(array, refn) ob = mesh.on_boundary # solve for each source patch npatch = abstract.get_patch_count(array) source_patch = np.arange(npatch) dest_patch = np.arange(npatch) # patches = abstract.get_patches_from_array(array) # patch_areas = np.array([p.area for p in patches]) for sid in source_patch: # get RHS b = np.array(F[:, sid].todense()) # solve start = timer() # conjugate so phase is consistent with -iwt convention used by h2lib if use_fluid: x = np.conj(Glu.lusolve(b)) else: x = Glu.solve(b) # doesn't work right yet... time_solve = timer() - start x[ob] = 0 # average displacement over patches x_patch = (AVG.T).dot(x) # write patch displacement results to frequency response database data = {} data['frequency'] = repeat(f) data['wavenumber'] = repeat(k) data['source_patch'] = repeat(sid) data['dest_patch'] = dest_patch data['displacement_real'] = np.real(x_patch) data['displacement_imag'] = np.imag(x_patch) data['time_solve'] = repeat(time_solve) with write_lock: database.append_patch_to_patch_freq_resp(file, **data) # write node displacement results to frequency response database data = {} data['node_id'] = range(len(mesh.vertices)) data['x'] = mesh.vertices[:, 0] data['y'] = mesh.vertices[:, 1] data['z'] = mesh.vertices[:, 2] data['frequency'] = repeat(f) data['wavenumber'] = repeat(k) data['source_patch'] = repeat(sid) data['displacement_real'] = np.real(x) data['displacement_imag'] = np.imag(x) with write_lock: database.append_patch_to_node_freq_resp(file, **data) with write_lock: util.update_progress(file, job_id)
def main(cfg, args): ''' Script entry point. ''' # get parameters from config and args file = args.file write_over = args.write_over threads = args.threads if args.threads else multiprocessing.cpu_count() f_start, f_stop, f_step = cfg.freqs c = cfg.sound_speed # calculate job-related values freqs = np.arange(f_start, f_stop + f_step, f_step) wavenums = 2 * np.pi * freqs / c is_complete = None njobs = len(freqs) ijob = 0 # check for existing file if os.path.isfile(file): if write_over: # if file exists, write over # remove existing files os.remove(file) # create databases database.create_db(file, **cfg._asdict()) util.create_progress_table(file, njobs) # append node information amesh = Mesh.from_abstract(abstract.load(cfg.array_config), refn=cfg.mesh_refn) nodes = amesh.vertices database.append_node(file, node_id=range(len(nodes)), x=nodes[:, 0], y=nodes[:, 1], z=nodes[:, 2]) else: # continue from current progress is_complete, ijob = util.get_progress(file) if np.all(is_complete): return else: # make directories if they do not exist file_dir = os.path.dirname(os.path.abspath(file)) if not os.path.exists(file_dir): os.makedirs(file_dir) # create databases database.create_db(file, **cfg._asdict()) util.create_progress_table(file, njobs) # append node information amesh = Mesh.from_abstract(abstract.load(cfg.array_config), refn=cfg.mesh_refn) nodes = amesh.vertices database.append_node(file, node_id=range(len(nodes)), x=nodes[:, 0], y=nodes[:, 1], z=nodes[:, 2]) # start multiprocessing pool and run process try: write_lock = multiprocessing.Lock() pool = multiprocessing.Pool(threads, initializer=init_process, initargs=(write_lock, abstract.dumps(cfg), file), maxtasksperchild=1) jobs = util.create_jobs((freqs, 1), (wavenums, 1), mode='zip', is_complete=is_complete) result = pool.imap_unordered(run_process, jobs, chunksize=1) for r in tqdm(result, desc='Running', total=njobs, initial=ijob): pass postprocess(file, cfg.freq_interp) except Exception as e: print(e) finally: pool.close() pool.terminate()
pat.theta_min) y1 = pat.position[1] + pat.radius_max * np.sin( pat.theta_min) line0 = plt.Line2D([x0, x1], [y0, y1], c='black', lw=1) ax.add_artist(line0) elif mem.shape.lower() in ['square', 's']: patch = patches.Rectangle(width=pat.length_x, height=pat.length_y, xy=(pat.position[0], pat.position[1]), ec='black', fill=False) ax.add_patch(patch) ax.set_aspect('equal') ax.autoscale() ax.set_xlabel('X (m)') ax.set_ylabel('Y (m)') ax.set_title('Array patch geometry') if __name__ == '__main__': file = sys.argv[1] array = abstract.load(file) fig_membranes(array) fig_patches(array)
def process(job): '''''' job_id, (f, k) = job # get options and parameters c = cfg.sound_speed rho = cfg.fluid_rho array = abstract.load(cfg.array_config) refn = cfg.mesh_refn # create finite element linear operators Gfe, Gfe_inv = fem.mbk_linear_operators(array, f, refn) # create boundary element linear operators hmkwrds = [ 'aprx', 'basis', 'admis', 'eta', 'eps', 'm', 'clf', 'eps_aca', 'rk', 'q_reg', 'q_sing', 'strict' ] hmargs = {k: getattr(cfg, k) for k in hmkwrds} Gbe, Gbe_inv = bem.z_linear_operators(array, f, c, refn, rho, **hmargs) # define total linear system and preconditioner G = Gfe + Gbe P = Gfe_inv # P = Gbe_inv * Gfe_inv # P = Gfe_inv * Gbe_inv # g = np.trace(MBK_inv.todense()) # mem_array = array.copy() # mem_array.elements = [array.elements[0],] # Bfe, Bfe_inv = fem.mbk_from_abstract(mem_array, f, refn) # Bfe = Bfe.todense() # Bfe_inv = np.linalg.inv(Bfe) # Bbe = bem.z_from_abstract(mem_array, k, refn=refn, format='FullFormat').data # Bbe_inv = np.linalg.inv(Bbe) # g = np.trace(Bfe.dot(Bbe_inv)) * len(array.elements) # P = Gbe_inv - (1 / (1 + g)) * Gbe_inv * Gfe * Gbe_inv # g = np.trace(Bbe.dot(Bfe_inv)) * len(array.elements) # P = Gfe_inv - (1 / (1 + g)) * Gfe_inv * Gbe * Gfe_inv # create patch pressure load F = fem.f_from_abstract(array, refn) # solve for each source patch npatch = abstract.get_patch_count(array) source_patch = np.arange(npatch) dest_patch = np.arange(npatch) for sid in source_patch: # get RHS b = P.dot(F[:, sid].todense()) # solve counter = util.Counter() start = timer() x, ecode = lgmres(G, b, tol=1e-6, maxiter=40, M=P, callback=counter.increment) time_solve = timer() - start # average displacement over patches x_patch = (F.T).dot(x) # / patch area? # write results to database data = {} data['frequency'] = repeat(f) data['wavenumber'] = repeat(k) data['source_patch'] = repeat(sid) data['dest_patch'] = dest_patch # data['source_membrane_id'] = repeat(mesh.membrane_ids[smask][0]) # data['dest_membrane_id'] = dest_membrane_ids # data['source_element_id'] = repeat(mesh.element_ids[smask][0]) # data['dest_element_id'] = dest_element_ids data['displacement_real'] = np.real(x_patch) data['displacement_imag'] = np.imag(x_patch) data['time_solve'] = repeat(time_solve) data['iterations'] = repeat(counter.count) with write_lock: update_database(file, **data) # add saving of metrics (solve time, lgmres steps etc.) with write_lock: util.update_progress(file, job_id)
def run(args): if args.config: cfg = Config(**abstract.load(args.config)) else: cfg = Config() return main(cfg, args)