def get_shell_mass_wrapper(dir_NM, model_1d): #def load_model_info(dir_base, RadialPNM_info, r_q, r_q_vals): # Load radius information for 3-D modes. _, header, _, _ = load_vsh_coefficients(dir_NM, 1, i_radius = 'all') # Calculate the mid-points. r_inner, r_outer = get_mid_points(header['i_sample'], header['r_sample']) # Extract the portions of the density model for each shell. shell_mass = get_shell_mass(header['i_sample'], r_inner, r_outer, model_1d, normalise = True) return shell_mass
def projection_wrapper_one_mode(dir_NM, i_mode, f, mode_info_1d, run_info_1d, l_max, shell_mass, max_f_diff = 0.2): # Dictionary for saving mode type as integer. mode_type_to_int_dict = {'R' : 0, 'S' : 1, 'T' : 2, 'T1' : 2, 'I' : 3, 'T0' : 3} # Find 1-D modes which are close in frequency to the 3-D mode. mode_info_1d = find_close_modes(f, mode_info_1d, max_f_diff) # Load the eigfunction of the 3-D mode. coeffs, header, _, _ = load_vsh_coefficients(dir_NM, i_mode, i_radius = 'all') r = header['r_sample'] n_radii = len(r) # Convert to real spherical harmonics. l_coeffs, m_coeffs, coeffs = convert_to_real_spherical_harmonics(coeffs, l_max) # Multiply V and W components by k. k = np.sqrt(l_coeffs * (l_coeffs + 1)) k[k == 0.0] = 1.0 coeffs[1, :, :] = k * coeffs[1, :, :] coeffs[2, :, :] = k * coeffs[2, :, :] coeffs[4, :, :] = k * coeffs[4, :, :] coeffs[5, :, :] = k * coeffs[5, :, :] #mode_type_test = 'T1' #mode_info_1d = {mode_type_test : mode_info_1d[mode_type_test]} # Count the modes. num_modes_1d_by_type_no_multiplets = dict() num_modes_1d_by_type_with_multiplets = dict() num_modes_1d_total_no_multiplets = 0 num_modes_1d_total_with_multiplets = 0 # for mode_type in mode_info_1d.keys(): num_modes_1d_by_type_no_multiplets[mode_type] = len(mode_info_1d[mode_type]['l']) # num_modes_1d_total_no_multiplets = num_modes_1d_total_no_multiplets + \ num_modes_1d_by_type_no_multiplets[mode_type] num_modes_1d_by_type_with_multiplets[mode_type] = 0 for j in range(num_modes_1d_by_type_no_multiplets[mode_type]): l_j = mode_info_1d[mode_type]['l'][j] num_modes_1d_by_type_with_multiplets[mode_type] = \ num_modes_1d_by_type_with_multiplets[mode_type] + ((2 * l_j) + 1) num_modes_1d_total_with_multiplets = num_modes_1d_total_with_multiplets + \ num_modes_1d_by_type_with_multiplets[mode_type] # Prepare to loop over all the 1-D modes and evaluate scalar product with the 3-D mode. # mode_type_out_array = np.zeros(num_modes_1d_total_with_multiplets, dtype = np.int) n = np.zeros(num_modes_1d_total_with_multiplets, dtype = np.int) l = np.zeros(num_modes_1d_total_with_multiplets, dtype = np.int) m = np.zeros(num_modes_1d_total_with_multiplets, dtype = np.int) product_real_part = np.zeros(num_modes_1d_total_with_multiplets) product_imag_part = np.zeros(num_modes_1d_total_with_multiplets) # i0 = 0 # Loop over mode types. for mode_type_1d in mode_info_1d.keys(): # Get mode type integer for saving output. mode_type_int = mode_type_to_int_dict[mode_type_1d] # Loop over modes of the given mode type. for j in range(num_modes_1d_by_type_no_multiplets[mode_type_1d]): print('Mode_type {:>2}, mode {:>4d} of {:>4d}'.format(mode_type_1d, j + 1, num_modes_1d_by_type_no_multiplets[mode_type_1d])) # Get n, l and multiplicity of current 1-D mode. n_j = mode_info_1d[mode_type_1d]['n'][j] l_j = mode_info_1d[mode_type_1d]['l'][j] multiplicity_j = (2 * l_j) + 1 # Get upper index in output array. i1 = i0 + multiplicity_j # All modes in the multiplet have the same mode type. mode_type_out_array[i0 : i1] = mode_type_int # All (2l + 1) modes in the multiplet have the same n and l value. n[i0 : i1] = n_j l[i0 : i1] = l_j # Find the indices of the given l value in the coefficient list. k = np.where((l_coeffs == l_j))[0] # Get the m values from the coefficient list. m[i0 : i1] = m_coeffs[k] # Do projection of real part. product_real_part[i0 : i1] = project_one_mode_onto_one_multiplet( header['r_sample'], header['i_sample'], shell_mass, coeffs[0, :, k], coeffs[1, :, k], coeffs[2, :, k], run_info_1d, mode_type_1d, mode_info_1d[mode_type_1d]['n'][j], mode_info_1d[mode_type_1d]['l'][j], mode_info_1d[mode_type_1d]['f'][j]) # Do projection of imaginary part. product_imag_part[i0 : i1] = project_one_mode_onto_one_multiplet( header['r_sample'], header['i_sample'], shell_mass, coeffs[3, :, k], coeffs[4, :, k], coeffs[5, :, k], run_info_1d, mode_type_1d, mode_info_1d[mode_type_1d]['n'][j], mode_info_1d[mode_type_1d]['l'][j], mode_info_1d[mode_type_1d]['f'][j]) # Prepare for next iteration of loop. i0 = i1 # Save output. out_fmt = '{:>2d} {:>5d} {:>5d} {:>+6d} {:>+19.12e} {:>+19.12e}\n' dir_processed = os.path.join(dir_NM, 'processed') dir_projections = os.path.join(dir_processed, 'projections') mkdir_if_not_exist(dir_projections) file_out = 'mode_{:>05d}.txt'.format(i_mode) path_out = os.path.join(dir_projections, file_out) print('Writing to {:}'.format(path_out)) with open(path_out, 'w') as out_id: for k in range(num_modes_1d_total_with_multiplets): out_id.write(out_fmt.format( mode_type_out_array[k], n[k], l[k], m[k], product_real_part[k], product_imag_part[k])) return
def plot_all_coeff_profiles(dir_PM, dir_NM, i_mode, l, l_max, fmt='png', mode_real_or_complex='real', multiply_by_k=True, compare_info=None, show=True): # Load comparison eigenfunction. if compare_info is not None: eigfunc_dict = load_compare_eigfunc(compare_info) # Load the mode frequency. dir_processed = os.path.join(dir_NM, 'processed') file_eigval_list = os.path.join(dir_processed, 'eigenvalue_list.txt') i_mode_list, freq_list = read_eigenvalues(file_eigval_list) i_mode_list = np.array(i_mode_list, dtype=np.int) freq_list = np.array(freq_list) freq = freq_list[np.where(i_mode_list == i_mode)[0][0]] # Create the title. title = 'Mode {:>5d}, frequency {:>7.3f} mHz'.format(i_mode, freq) # Read the discontinuity radius information. path_discon_info = os.path.join(dir_PM, 'radii.txt') r_discons, state_outer = read_discon_file(path_discon_info) n_discons = len(r_discons) # Load the coefficients and radial coordinates. coeffs, header, _, _ = load_vsh_coefficients(dir_NM, i_mode, i_radius='all') r = header['r_sample'] ## Remove scaling factor. #coeffs = coeffs * header['eigvec_max'] # Convert to real. l_coeffs, m_coeffs, coeffs = convert_to_real_spherical_harmonics( coeffs, l_max) i_choose = np.where(l_coeffs == l)[0] m_choose = m_coeffs[i_choose] coeffs = coeffs[:, :, i_choose] num_choose = len(m_choose) # fig, ax_arr = plt.subplots(3, 2, figsize=(14.0, 11.0), sharex=True, sharey=True, constrained_layout=True) map_coeffs_to_ax = { 0: [0, 0], 1: [0, 1], 2: [0, 2], 3: [1, 0], 4: [1, 1], 5: [1, 2] } # Create colour scale. c_map = plt.get_cmap('rainbow_r') c_norm = mpl_colors.Normalize(vmin=0.0, vmax=(num_choose - 1.0)) for i in range(6): ax_i, ax_j = map_coeffs_to_ax[i] ax = ax_arr[ax_j, ax_i] for j in range(num_choose): color = c_map(c_norm(j)) ax.plot(coeffs[i, :, j], r, label='{:>+3d}'.format(m_choose[j]), color=color, alpha=0.5) #ax.legend() plt.show() return
def plot_eigenfunction_wrapper(dir_PM, dir_NM, i_mode, fmt='png', mode_real_or_complex='real', multiply_by_k=True, compare_info=None, show=True): # Load comparison eigenfunction. if compare_info is not None: eigfunc_dict = load_compare_eigfunc(compare_info) # Load the mode frequency. dir_processed = os.path.join(dir_NM, 'processed') file_eigval_list = os.path.join(dir_processed, 'eigenvalue_list.txt') i_mode_list, freq_list = read_eigenvalues(file_eigval_list) i_mode_list = np.array(i_mode_list, dtype=np.int) freq_list = np.array(freq_list) freq = freq_list[np.where(i_mode_list == i_mode)[0][0]] # Create the title. title = 'Mode {:>5d}, frequency {:>7.3f} mHz'.format(i_mode, freq) # Read the discontinuity radius information. path_discon_info = os.path.join(dir_PM, 'radii.txt') r_discons, state_outer = read_discon_file(path_discon_info) n_discons = len(r_discons) # Load the coefficients and radial coordinates. coeffs, header, _, _ = load_vsh_coefficients(dir_NM, i_mode, i_radius='all') r = header['r_sample'] # Remove scaling factor. coeffs = coeffs * header['eigvec_max'] # Calculate radial profiles from the coefficients. if mode_real_or_complex == 'real': U, V, W = get_radial_profiles_real(coeffs) elif mode_real_or_complex == 'complex': U, V, W = get_radial_profiles_complex(coeffs) # if multiply_by_k: # Load the mode identification information. path_ids = os.path.join(dir_processed, 'mode_ids_full.txt') _, l_list, _, _ = np.loadtxt(path_ids, dtype=np.int).T l = l_list[i_mode - 1] # Not 0- and 1-based indexing. k = np.sqrt(l * (l + 1)) V = k * V W = k * W # Adjust sign according to convention. U, V, W, X_max = check_sign_radial_profiles(r, U, V, W) fig = plt.figure(figsize=(6.0, 8.0)) ax = plt.gca() if compare_info is None: labels = ['U', 'V', 'W'] else: labels = ['{:} (NormalModes)'.format(x) for x in ['U', 'V', 'W']] arrays = [U, V, W] color_U = 'orangered' color_V = 'royalblue' color_W = 'mediumseagreen' colors = [color_U, color_V, color_W] for i in range(3): ax.plot(arrays[i], r, label=labels[i], color=colors[i]) ax.scatter(arrays[i], r, color=colors[i], s=3) if compare_info is not None: if compare_info['type'] == 'S': # Adjust sign according to convention. #eigfunc_dict['U'], eigfunc_dict['V'], _, _ = \ # check_sign_radial_profiles(eigfunc_dict['r'], # eigfunc_dict['U'], eigfunc_dict['V'], # np.zeros(len(eigfunc_dict['r']))) if np.sign(eigfunc_dict['U'][-1]) != np.sign(U[0]): eigfunc_dict['U'] = -1.0 * eigfunc_dict['U'] eigfunc_dict['V'] = -1.0 * eigfunc_dict['V'] rms_amp = get_rms_amp(r, U, V, W) rms_compare = get_rms_amp(eigfunc_dict['r'], eigfunc_dict['U'], eigfunc_dict['V'], np.zeros(len(eigfunc_dict['r']))) rms_ratio = rms_amp / rms_compare colors = [color_U, color_V] components = ['U', 'V'] for key in components: eigfunc_dict[key] = eigfunc_dict[key] * rms_ratio else: raise NotImplementedError #labels = ['{:} (Ouroboros)'.format(x) for x in components] labels = ['{:} (Mineos)'.format(x) for x in components] arrays = [eigfunc_dict[key] for key in components] n_components = len(components) for i in range(n_components): ax.plot(arrays[i], eigfunc_dict['r'], color=colors[i], linestyle=':', label=labels[i]) # Set axis limits. x_buff = 1.1 ax.set_xlim([-x_buff * X_max, x_buff * X_max]) ax.set_ylim([0.0, r_discons[0]]) # Draw guidelines. guideline_kwargs = {'linestyle': ':', 'color': 'k'} ax.axvline(**guideline_kwargs) if n_discons > 1: for i in range(1, n_discons): ax.axhline(r_discons[i], **guideline_kwargs) ax.legend() font_size_label = 12 font_size_title = 16 ax.set_xlabel('Eigenfunction', fontsize=font_size_label) ax.set_ylabel('Radius / km', fontsize=font_size_label) ax.set_title(title, fontsize=font_size_title) plt.tight_layout() # Save the figure. dir_plot = os.path.join(dir_processed, 'plots') name_fig = 'eigenfunctions_{:>05d}.{:}'.format(i_mode, fmt) path_fig = os.path.join(dir_plot, name_fig) print('Saving figure to {:}'.format(path_fig)) save_figure(path_fig, fmt) if show: plt.show() plt.close() return
def characterise_all_modes_full(dir_NM): option = 'full' #i_radius = None # Get a list of modes. #i_mode_list = get_list_of_modes_from_output_files(dir_NM) i_mode_list = get_list_of_modes_from_coeff_files(dir_NM, option) n_modes = len(i_mode_list) # Define directories. dir_processed = os.path.join(dir_NM, 'processed') # Loop over all modes. first_iteration = True for i, i_mode in enumerate(i_mode_list): print('Characterising mode {:>5d}, item {:>5d} of {:>5d}'.format( i_mode, i + 1, n_modes)) # Load the complex VSH coefficients. coeffs, header_info, _, _ = load_vsh_coefficients(dir_NM, i_mode, i_radius='all') if coeffs.shape[1] == 3: modes_are_complex = False elif coeffs.shape[1] == 6: modes_are_complex = True coeffs_new = np.zeros((coeffs.shape[0], 3, coeffs.shape[2]), dtype=np.complex) coeffs_new[:, 0, :] = coeffs[:, 0, :] + 1.0j * coeffs[:, 3, :] coeffs_new[:, 1, :] = coeffs[:, 1, :] + 1.0j * coeffs[:, 4, :] coeffs_new[:, 2, :] = coeffs[:, 2, :] + 1.0j * coeffs[:, 5, :] coeffs = coeffs_new if first_iteration: # Infer the maximum l-value used. n_coeffs = coeffs.shape[2] l_max = (int((np.round(np.sqrt(8 * n_coeffs + 1)) - 1)) // 2) - 1 # Get the list of l and m values of the coefficients. l, m = make_l_and_m_lists(l_max) # Prepare output arrays. E_UVW = np.zeros((3, n_modes)) E_of_l = np.zeros((l_max + 1, n_modes)) r_max = np.zeros(n_modes) i_region_max = np.zeros(n_modes, dtype=np.int) # Calculate weights of each shell. volume_weights = calculate_weights(header_info['r_sample']) first_iteration = False # Calculate the power distribution. EU_i, EV_i, EW_i, E_i, E_of_l_i = calculate_power_distribution_full( coeffs, l, volume_weights, print_=False) # Normalise by the sum. EU_i = EU_i / E_i EV_i = EV_i / E_i EW_i = EW_i / E_i E_of_l_i = E_of_l_i / E_i # Store. E_UVW[0, i] = EU_i E_UVW[1, i] = EV_i E_UVW[2, i] = EW_i E_of_l[:, i] = E_of_l_i # r_max[i] = header_info['r_max'] i_region_max[i] = header_info['i_region_max'] # Save mode characterisation information. array_out = np.array([*E_UVW, *E_of_l, r_max, i_region_max]) path_out = os.path.join(dir_NM, 'processed', 'characterisation_full.npy') print('Saving mode characterisation information to {:}'.format(path_out)) np.save(path_out, array_out) # Find l-value and type for each mode. l = np.zeros(n_modes, dtype=np.int) shell = np.zeros(n_modes, dtype=np.int) # type_: 0: radial, 1: spheroidal, 2: toroidal type_ = np.zeros(n_modes, dtype=np.int) for i in range(n_modes): shell[i] = i_region_max[i] // 3 # Find dominant l-value. l[i] = np.argmax(E_of_l[:, i]) if l[i] == 0: type_[i] = 0 else: # Check if spheroidal or toroidal power is greater. if ((E_UVW[0, i] + E_UVW[1, i]) > E_UVW[2, i]): type_[i] = 1 else: type_[i] = 2 path_out_ids = os.path.join(dir_NM, 'processed', 'mode_ids_full.txt') out_array_ids = np.array([i_mode_list, l, type_, shell]) print('Saving mode identifications to {:}'.format(path_out_ids)) np.savetxt(path_out_ids, out_array_ids.T, fmt='%i') return
def characterise_all_modes_quick(dir_NM): option = 'quick' i_radius = None # Get a list of modes. #i_mode_list = get_list_of_modes_from_output_files(dir_NM) i_mode_list = get_list_of_modes_from_coeff_files(dir_NM, option) n_modes = len(i_mode_list) # Define directories. dir_processed = os.path.join(dir_NM, 'processed') # Loop over all modes. first_iteration = True for i, i_mode in enumerate(i_mode_list): print('Characterising mode {:>5d}'.format(i_mode)) coeffs, header_info, r_sample, i_sample = \ load_vsh_coefficients(dir_NM, i_mode, i_radius = i_radius) if coeffs.shape[0] == 3: modes_are_complex = False Ulm, Vlm, Wlm = coeffs elif coeffs.shape[0] == 6: modes_are_complex = True Ulm_real, Vlm_real, Wlm_real, Ulm_imag, Vlm_imag, Wlm_imag = coeffs else: raise ValueError if first_iteration: # Infer the maximum l-value used. if modes_are_complex: n_coeffs = len(Ulm_real) else: n_coeffs = len(Ulm) l_max = (int((np.round(np.sqrt(8 * n_coeffs + 1)) - 1)) // 2) - 1 # Get the list of l and m values of the coefficients. l, m = make_l_and_m_lists(l_max) # Prepare output arrays. E_UVW = np.zeros((3, n_modes)) E_of_l = np.zeros((l_max + 1, n_modes)) r_max = np.zeros(n_modes) i_region_max = np.zeros(n_modes, dtype=np.int) first_iteration = False # Calculate the power distribution. if modes_are_complex: EU_i, EV_i, EW_i, E_i, E_of_l_i = \ calculate_power_distribution_quick_cplx( Ulm_real, Vlm_real, Wlm_real, Ulm_imag, Vlm_imag, Wlm_imag, l, print_ = False) else: EU_i, EV_i, EW_i, E_i, E_of_l_i = calculate_power_distribution_quick_real( Ulm, Vlm, Wlm, l, print_=False) # Normalise by the sum. EU_i = EU_i / E_i EV_i = EV_i / E_i EW_i = EW_i / E_i E_of_l_i = E_of_l_i / E_i # Store. E_UVW[0, i] = EU_i E_UVW[1, i] = EV_i E_UVW[2, i] = EW_i E_of_l[:, i] = E_of_l_i # r_max[i] = r_sample i_region_max[i] = i_sample # Save mode characterisation information. array_out = np.array([*E_UVW, *E_of_l, r_max, i_region_max]) path_out = os.path.join(dir_NM, 'processed', 'characterisation_quick.npy') print('Saving mode characterisation information to {:}'.format(path_out)) np.save(path_out, array_out) # Find l-value and type for each mode. l = np.zeros(n_modes, dtype=np.int) shell = np.zeros(n_modes, dtype=np.int) # type_: 0: radial, 1: spheroidal, 2: toroidal type_ = np.zeros(n_modes, dtype=np.int) for i in range(n_modes): shell[i] = i_region_max[i] // 3 # Find dominant l-value. l[i] = np.argmax(E_of_l[:, i]) if l[i] == 0: type_[i] = 0 else: # Check if spheroidal or toroidal power is greater. if ((E_UVW[0, i] + E_UVW[1, i]) > E_UVW[2, i]): type_[i] = 1 else: type_[i] = 2 path_out_ids = os.path.join(dir_NM, 'processed', 'mode_ids_quick.txt') out_array_ids = np.array([i_mode_list, l, type_, shell]) print('Saving mode identifications to {:}'.format(path_out_ids)) np.savetxt(path_out_ids, out_array_ids.T, fmt='%i') return