def plot_Q_criterion(self,vals_list,x_split_pair=None,PhyTime=None,y_limit=None,y_mode='half_channel',Y_plus=True,avg_data=None,colors=None,surf_kw=None,fig=None,ax=None,**kwargs): PhyTime = self.check_PhyTime(PhyTime) vals_list = misc_utils.check_list_vals(vals_list) if y_limit is not None: y_lim_int = indexing.ycoords_from_norm_coords(self.avg_data,[y_limit],mode=y_mode)[0][0] else: y_lim_int = None kwargs = cplt.update_subplots_kw(kwargs,subplot_kw={'projection':'3d'}) fig, ax = cplt.create_fig_ax_with_squeeze(fig=fig,ax=ax,**kwargs) Q = self.Q_crit_calc(PhyTime) for i,val in enumerate(vals_list): if colors is not None: color = colors[i%len(colors)] surf_kw['facecolor'] = color fig, ax1 = Q.plot_isosurface('Q',val,time=PhyTime,y_limit=y_lim_int, x_split_pair=x_split_pair,fig=fig,ax=ax, surf_kw=surf_kw) ax.axes.set_ylabel(r'$x/\delta$') ax.axes.set_xlabel(r'$z/\delta$') ax.axes.invert_xaxis() return fig, ax1
def plot(self, budget_terms=None, PhyTime=None, fig=None, ax=None, line_kw=None, **kwargs): budget_terms = self._check_terms(budget_terms) kwargs = cplt.update_subplots_kw(kwargs, figsize=[10, 5]) fig, ax = cplt.create_fig_ax_with_squeeze(fig, ax, **kwargs) line_kw = cplt.update_line_kw(line_kw) xaxis_vals = self.avg_data._return_xaxis() for comp in budget_terms: budget_term = self.budgetDF[PhyTime, comp].copy() label = r"%s" % comp.title() ax.cplot(xaxis_vals, budget_term, label=label, **line_kw) ax.cplot(xaxis_vals, np.sum(self.budgetDF.values, axis=0), label="Total") ncol = cplt.get_legend_ncols(len(budget_terms)) ax.clegend(ncol=ncol, vertical=False) return fig, ax
def plot_vector(self,plane,modes,axis_vals,y_mode='half_channel',spacing=(1,1),scaling=1,fig=None,ax=None,quiver_kw=None,**kwargs): FluctDF = self._getFluctDF(modes) plane = self.Domain.out_to_in(plane) axis_vals = misc_utils.check_list_vals(axis_vals) plane, coord = FluctDF.CoordDF.check_plane(plane) if coord == 'y': axis_vals = indexing.ycoords_from_coords(self.avg_data,axis_vals,mode=y_mode)[0] int_vals = indexing.ycoords_from_norm_coords(self.avg_data,axis_vals,mode=y_mode)[0] else: int_vals = axis_vals = indexing.true_coords_from_coords(self.CoordDF,coord,axis_vals) x_size, z_size = FluctDF.get_unit_figsize(plane) figsize=[x_size,z_size*len(axis_vals)] axes_output = True if isinstance(ax,mpl.axes.Axes) else False kwargs = cplt.update_subplots_kw(kwargs,figsize=figsize) fig, ax = cplt.create_fig_ax_without_squeeze(len(axis_vals),fig=fig,ax=ax,**kwargs) title_symbol = misc_utils.get_title_symbol(coord,y_mode,False) for i, val in enumerate(int_vals): fig, ax[i] = FluctDF.plot_vector(plane,val,time=None,spacing=spacing,scaling=scaling, fig=fig,ax=ax[i],quiver_kw=quiver_kw) ax[i].axes.set_xlabel(r"$%s/\delta$"%slice[0]) ax[i].axes.set_ylabel(r"$%s/\delta$"%slice[1]) ax[i].axes.set_title(r"$%s = %.2g$"%(title_symbol,axis_vals[i]),loc='right') if axes_output: return fig, ax[0] else: return fig, ax
def plot_contour(self,comp,modes,fig=None,ax=None,pcolor_kw=None,**kwargs): kwargs = cplt.update_subplots_kw(kwargs,figsize=[7,5]) fig, ax = cplt.create_fig_ax_with_squeeze(fig=fig,ax=ax,**kwargs) coeffs = self.POD_coeffs[sorted(modes)] reconstruct_arrays = np.multiply(self.POD.POD_modesDF[comp][:,:,modes],coeffs) flow_reconstruct = np.sum(reconstruct_arrays,axis=-1) x_array = self.avg_data.CoordDF[self.POD._plane[0]] y_array = self.avg_data.CoordDF[self.POD._plane[1]] X, Z = np.meshgrid(x_array, y_array) pcolor_kw = cplt.update_pcolor_kw(pcolor_kw) ax1 = ax.pcolormesh(X,Z,flow_reconstruct,**pcolor_kw) ax1.axes.set_xlabel(r"$%s/\delta$" % self.POD._plane[0]) ax1.axes.set_ylabel(r"$%s/\delta$" % self.POD._plane[1]) ax1.axes.set_aspect('equal') cbar=fig.colorbar(ax1,ax=ax) cbar.set_label(r"$%s^\prime$"%comp) fig.tight_layout() return fig, ax1
def spectrum_contour(self, comp, axis_vals, axis_mode='half_channel', fig=None, ax=None, pcolor_kw=None, **kwargs): if not comp in ('x', 'z'): raise ValueError(" Variable `comp' must eiher be 'x' or 'z'\n") axis_vals = misc_utils.check_list_vals(axis_vals) y_index_axis_vals = indexing.y_coord_index_norm( self._avg_data, axis_vals, None, axis_mode) Ruu_all = self.autocorrDF[comp] #[:,axis_vals,:] shape = Ruu_all.shape Ruu = np.zeros((shape[0], len(axis_vals), shape[2])) for i, vals in zip(range(shape[2]), y_index_axis_vals): Ruu[:, :, i] = Ruu_all[:, vals, i] kwargs = cplt.update_subplots_kw(kwargs, figsize=[10, 4 * len(axis_vals)]) fig, ax = cplt.create_fig_ax_without_squeeze(len(axis_vals), fig=fig, ax=ax, **kwargs) coord = self._meta_data.CoordDF[comp].copy()[:shape[0]] x_axis = self._avg_data._return_xaxis() pcolor_kw = cplt.update_pcolor_kw(pcolor_kw) for i in range(len(axis_vals)): wavenumber_spectra = np.zeros((int(0.5 * shape[0]) + 1, shape[2]), dtype=np.complex128) for j in range(shape[2]): wavenumber_spectra[:, j] = fft.rfft(Ruu[:, i, j]) comp_size = shape[0] wavenumber_comp = 2 * np.pi * fft.rfftfreq(comp_size, coord[1] - coord[0]) X, Y = np.meshgrid(x_axis, wavenumber_comp) ax[i] = ax[i].pcolormesh(X, Y, np.abs(wavenumber_spectra), **pcolor_kw) ax[i].axes.set_ylabel(r"$\kappa_%s$" % comp) title = r"$%s=%.3g$"%("y" if axis_mode=='half_channel' \ else r"\delta_u" if axis_mode=='disp_thickness' \ else r"\theta" if axis_mode=='mom_thickness' else "y^+", axis_vals[i] ) ax[i].axes.set_ylim( [np.amin(wavenumber_comp[1:]), np.amax(wavenumber_comp)]) ax[i].axes.set_title(title) # ,fontsize=15,loc='left') fig.colorbar(ax[i], ax=ax[i].axes) return fig, ax
def plot_lambda2(self,vals_list,x_split_pair=None,PhyTime=None,y_limit=None,y_mode='half_channel',Y_plus=True,avg_data=None,colors=None,surf_kw=None,fig=None,ax=None,**kwargs): """ Creates isosurfaces for the lambda 2 criterion Parameters ---------- vals_list : list of floats isovalues to be plotted x_split_list : list, optional Separating domain into different streamwise lengths useful if the domain is much longer than its width, by default None PhyTime : float, optional Physical time to be plotted, None can be used if the instance contains a single time, by default None ylim : float, optional wall-normal extent of the isosurface plot, by default None Y_plus : bool, optional Whether the above value is in wall units, by default True avg_data : CHAPSim_AVG, optional Instance of avg_data need if Y_plus is True, by default None colors : list of str, optional list to represent the order of the colors to be plotted, by default None fig : %(fig)s, optional Pre-existing figure, by default None ax : %(ax)s, optional Pre-existing axes, by default None Returns ------- %(fig)s, %(ax)s output figure and axes objects """ PhyTime = self.check_PhyTime(PhyTime) vals_list = misc_utils.check_list_vals(vals_list) if y_limit is not None: y_lim_int = indexing.ycoords_from_norm_coords(self.avg_data,[y_limit],mode=y_mode)[0][0] else: y_lim_int = None kwargs = cplt.update_subplots_kw(kwargs,subplot_kw={'projection':'3d'}) fig, ax = cplt.create_fig_ax_with_squeeze(fig=fig,ax=ax,**kwargs) lambda_2DF = self.lambda2_calc(PhyTime) for i,val in enumerate(vals_list): if colors is not None: color = colors[i%len(colors)] surf_kw['facecolor'] = color fig, ax1 = lambda_2DF.plot_isosurface('lambda_2',val,time=PhyTime,y_limit=y_lim_int, x_split_pair=x_split_pair,fig=fig,ax=ax, surf_kw=surf_kw) ax.axes.set_ylabel(r'$x/\delta$') ax.axes.set_xlabel(r'$z/\delta$') ax.axes.invert_xaxis() return fig, ax1
def autocorr_contour_x(self, comp, axis_vals, axis_mode='half_channel', norm=True, fig=None, ax=None, pcolor_kw=None, **kwargs): if not comp in ('x', 'z'): raise ValueError(" Variable `comp' must eiher be 'x' or 'z'\n") axis_vals = misc_utils.check_list_vals(axis_vals) y_index_axis_vals = indexing.y_coord_index_norm( self._avg_data, axis_vals, None, axis_mode) Ruu_all = self.autocorrDF[comp].copy() shape = Ruu_all.shape Ruu = np.zeros((shape[0], len(axis_vals), shape[2])) for i, vals in zip(range(shape[2]), y_index_axis_vals): Ruu[:, :, i] = Ruu_all[:, vals, i] if norm: Ruu_0 = Ruu[0].copy() for i in range(shape[0]): Ruu[i] /= Ruu_0 kwargs = cplt.update_subplots_kw(kwargs, figsize=[10, 4 * len(axis_vals)]) fig, ax = cplt.create_fig_ax_without_squeeze(len(axis_vals), fig=fig, ax=ax, **kwargs) x_axis = self._avg_data._return_xaxis() coord = self._meta_data.CoordDF[comp].copy()[:shape[0]] pcolor_kw = cplt.update_pcolor_kw(pcolor_kw) ax_out = [] for i in range(len(axis_vals)): X, Y = np.meshgrid(x_axis, coord) ax[i] = ax[i].pcolormesh(X, Y, Ruu[:, i], **pcolor_kw) ax[i].axes.set_ylabel(r"$\Delta %s/\delta$" % comp) title = r"$%s=%.3g$"%("y" if axis_mode=='half_channel' \ else r"\delta_u" if axis_mode=='disp_thickness' \ else r"\theta" if axis_mode=='mom_thickness' else r"y^+", axis_vals[i] ) ax[i].axes.set_title(title, loc='left') fig.colorbar(ax[i], ax=ax[i].axes) fig.tight_layout() return fig, ax
def plot_coeffs(self,n_modes,fig=None,ax=None,**kwargs): if n_modes > self.POD_coeffs.size: msg = "The number of modes must be less than the number of available coefficients" raise ValueError(msg) kwargs = cplt.update_subplots_kw(kwargs,figsize=[7,5]) fig, ax = cplt.create_fig_ax_with_squeeze(fig,ax,**kwargs) modes = [x+1 for x in range(n_modes)] ax.bar(modes,self.POD_coeffs[:n_modes]) ax.set_xlabel(r"Modes") ax.set_ylabel(r"Coefficient $a$") return fig, ax
def plot_energy_levels(self, n_modes, fig=None, ax=None, **kwargs): kwargs = cplt.update_subplots_kw(kwargs, figsize=[7, 5]) fig, ax = cplt.create_fig_ax_with_squeeze(fig, ax, **kwargs) total_energy = np.sum(self.EigenVals) energy_prop = self.EigenVals[:n_modes] / total_energy modes = [x + 1 for x in range(n_modes)] ax.bar(modes, energy_prop) ax.set_xlabel(r"Modes") ax.set_ylabel("Proportion of energy") return fig, ax
def _plot_budget_x(self, budget_terms, y_vals_list, Y_plus=True, PhyTime=None, fig=None, ax=None, **kwargs): budget_terms = self._check_terms(budget_terms) kwargs = cplt.update_subplots_kw(kwargs, figsize=[10, 5]) fig, ax = cplt.create_fig_ax_with_squeeze(fig, ax**kwargs) xaxis_vals = self.avg_data._return_xaxis() for comp in budget_terms: if y_vals_list != 'max': if Y_plus: y_index = indexing.Y_plus_index_calc( self, self.CoordDF, y_vals_list) else: y_index = indexing.coord_index_calc( self.CoordDF, 'y', y_vals_list) budget_term = self.budgetDF[PhyTime, comp] y_vals_list = indexing.ycoords_from_coords(self, y_vals_list, mode='wall')[0] for i, y_val in enumerate(y_vals_list): ax.cplot(budget_term[i], label=r"%s $y^+=%.2g$" % (comp, y_val)) ncol = cplt.get_legend_ncols( len(budget_terms) * len(y_vals_list)) ax.clegend(vertical=False, ncol=ncol, fontsize=16) else: budget_term = self.budgetDF[PhyTime, comp] budget_term = np.amax(budget_term, axis=0) ax.cplot(xaxis_vals, budget_term, label=r"maximum %s" % comp) ncol = cplt.get_legend_ncols(len(budget_terms)) ax.clegend(vertical=False, ncol=ncol, fontsize=16) fig.tight_layout() return fig, ax
def plot_fluct3D_xz(self, comp, y_vals, y_mode='half-channel', PhyTime=None, x_split_pair=None, fig=None, ax=None, surf_kw=None, **kwargs): y_vals = misc_utils.check_list_vals(y_vals) PhyTime = self.check_PhyTime(PhyTime) y_int_vals = indexing.ycoords_from_norm_coords(self.avg_data, y_vals, mode=y_mode)[0] axes_output = True if isinstance(ax, mpl.axes.Axes) else False kwargs = cplt.update_subplots_kw(kwargs, subplot_kw={'projection': '3d'}, antialiased=True) fig, ax = cplt.create_fig_ax_without_squeeze(len(y_int_vals), fig=fig, ax=ax, **kwargs) for i, val in enumerate(y_int_vals): fig, ax[i] = self.fluctDF.plot_surf(comp, 'xz', val, time=PhyTime, x_split_pair=x_split_pair, fig=fig, ax=ax[i], surf_kw=surf_kw) ax[i].axes.set_ylabel(r'$x/\delta$') ax[i].axes.set_xlabel(r'$z/\delta$') ax[i].axes.set_zlabel(r'$%s^\prime$' % comp) ax[i].axes.invert_xaxis() if axes_output: return fig, ax[0] else: return fig, ax
def plot_contour(self,comp,modes,axis_vals,plane='xz',y_mode='wall',fig=None,ax=None,pcolor_kw=None,**kwargs): FluctDF = self._getFluctDF(modes) plane = self.Domain.out_to_in(plane) axis_vals = misc_utils.check_list_vals(axis_vals) plane, coord = FluctDF.CoordDF.check_plane(plane) if coord == 'y': axis_vals = indexing.ycoords_from_coords(self.avg_data,axis_vals,mode=y_mode)[0] int_vals = indexing.ycoords_from_norm_coords(self.avg_data,axis_vals,mode=y_mode)[0] else: int_vals = axis_vals = indexing.true_coords_from_coords(self.CoordDF,coord,axis_vals) # int_vals = indexing.coord_index_calc(self.CoordDF,coord,axis_vals) x_size, z_size = FluctDF.get_unit_figsize(plane) figsize=[x_size,z_size*len(axis_vals)] axes_output = True if isinstance(ax,mpl.axes.Axes) else False kwargs = cplt.update_subplots_kw(kwargs,figsize=figsize) fig, ax = cplt.create_fig_ax_without_squeeze(len(axis_vals),fig=fig,ax=ax,**kwargs) title_symbol = misc_utils.get_title_symbol(coord,y_mode,False) for i,val in enumerate(int_vals): fig, ax1 = FluctDF.plot_contour(comp,plane,val,time=None,fig=fig,ax=ax[i],pcolor_kw=pcolor_kw) ax1.axes.set_xlabel(r"$%s/\delta$" % plane[0]) ax1.axes.set_ylabel(r"$%s/\delta$" % plane[1]) ax1.axes.set_title(r"$%s=%.2g$"%(title_symbol,axis_vals[i]),loc='right') cbar=fig.colorbar(ax1,ax=ax[i]) cbar.set_label(r"$%s^\prime$"%comp) ax[i]=ax1 ax[i].axes.set_aspect('equal') if axes_output: return fig, ax[0] else: return fig, ax
def _plot_integral_budget(self, budget_terms=None, PhyTime=None, wall_units=True, fig=None, ax=None, line_kw=None, **kwargs): y_coords = self.avg_data.CoordDF['y'] budget_terms = self._check_terms(budget_terms) u_tau_star, delta_v_star = self.avg_data._wall_unit_calc(PhyTime) kwargs = cplt.update_subplots_kw(kwargs, figsize=[10, 5]) fig, ax = cplt.create_fig_ax_with_squeeze(fig, ax, **kwargs) line_kw = cplt.update_line_kw(line_kw) xaxis_vals = self.avg_data._return_xaxis() for comp in budget_terms: integral_budget = np.zeros(self.avg_data.shape[1]) budget_term = self.budgetDF[PhyTime, comp].copy() for i in range(self.avg_data.shape[1]): integral_budget[i] = 0.5 * integrate.simps( budget_term[:, i], y_coords) if wall_units: delta_star = 1.0 integral_budget[i] /= (delta_star * u_tau_star[i]**3 / delta_v_star[i]) label = r"$\int^{\delta}_{-\delta}$ %s $dy$" % comp.title() ax.cplot(xaxis_vals, integral_budget, label=label, **line_kw) ncol = cplt.get_legend_ncols(len(budget_terms)) ax.clegend(ncol=ncol, vertical=False) #ax.grid() return fig, ax
def plot_mode_contour(self, comp, modes, fig=None, ax=None, pcolor_kw=None, **kwargs): modes = misc_utils.check_list_vals(modes) ax_layout = len(modes) figsize = [10, 3 * len(modes)] kwargs = cplt.update_subplots_kw(kwargs, figsize=figsize) fig, ax = cplt.create_fig_ax_without_squeeze(ax_layout, fig=fig, ax=ax, **kwargs) pcolor_kw = cplt.update_pcolor_kw(pcolor_kw) x_coords = self.avg_data.CoordDF[self._plane[0]] y_coords = self.avg_data.CoordDF[self._plane[1]] X, Y = np.meshgrid(x_coords, y_coords) PODmodes = self.POD_modesDF[None, comp] coord = list('xyz') coord.remove(self._plane[0]) coord.remove(self._plane[1]) for i, mode in enumerate(modes): ax[i] = ax[i].pcolormesh(X, Y, PODmodes[:, :, mode], **pcolor_kw) ax[i].axes.set_xlabel(r"$%s/\delta$" % self._plane[0]) ax[i].axes.set_ylabel(r"$%s/\delta$" % self._plane[1]) ax[i].axes.set_title(r"Mode %d" % (mode + 1), loc='left') ax[i].axes.set_title(r"$%s/\delta$" % coord[0], loc='right') return fig, ax
def plot_joint_PDF(self, xy_list, contour_kw=None, fig=None, ax=None, **kwargs): kwargs = cplt.update_subplots_kw(kwargs, figsize=[8, 4 * len(xy_list)]) fig, ax = cplt.create_fig_ax_without_squeeze(len(xy_list), fig=fig, ax=ax, **kwargs) ax = ax.flatten() contour_kw = cplt.update_contour_kw(contour_kw) i = 0 y_unit = r"y/\delta" if self._y_mode=='half_channel' \ else r"\delta_u" if self._y_mode=='disp_thickness' \ else r"\theta" if self._y_mode=='mom_thickness' else r"y^+" \ if self._y_mode=='wall' and any(self._x_loc_norm!=0) else r"y^{+0}" for xy in xy_list: u_array = self.u_arrayDF[xy] v_array = self.v_arrayDF[xy] pdf_array = self.pdf_arrayDF[xy] U_mesh, V_mesh = np.meshgrid(u_array, v_array) C = ax[i].contour( U_mesh, V_mesh, pdf_array, **contour_kw ) #seaborn.kdeplot(x=x_vals,y=y_vals,ax=ax[i],**pdf_kwargs) ax[i].set_xlabel(r"$u'$") ax[i].set_ylabel(r"$v'$") ax[i].set_title(r"$x/\delta=%g$, $%s=%g$" % (xy[0], y_unit, xy[1]), loc='right') i += 1 fig.tight_layout() return fig, ax
def line_plot(self, h_list, coord_list, prop_dir, x_vals=0, y_mode='half_channel', norm=False, fig=None, ax=None, line_kw=None, **kwargs): assert x_vals is None or not hasattr(x_vals, '__iter__') kwargs = cplt.update_subplots_kw(kwargs, figsize=[12, 5 * len(coord_list)]) fig, ax = cplt.create_fig_ax_without_squeeze(4, len(coord_list), fig=fig, ax=ax, **kwargs) ax = ax.reshape((4, len(coord_list))) if prop_dir == 'y': index = [self._avg_data._return_index(x) for x in coord_list] elif prop_dir == 'x': index = indexing.y_coord_index_norm(self._avg_data, coord_list, x_vals, y_mode) if x_vals is not None: index = list(itertools.chain(*index)) else: raise ValueError( "The propagation direction of the quadrant analysis must be `x' or `y'" ) if norm: avg_time = list( set([x[0] for x in self._avg_data.UU_tensorDF.index]))[0] uv = self._avg_data.UU_tensorDF[avg_time, 'uv'] coords = self._meta_data.CoordDF[prop_dir] unit=r"x/\delta"if prop_dir =='y' else r"y/\delta" if y_mode=='half_channel' \ else r"\delta_u" if y_mode=='disp_thickness' \ else r"\theta" if y_mode=='mom_thickness' else r"y^+" \ if x_vals is None or x_vals!=0 else r"y^{+0}" line_kw = cplt.update_line_kw(line_kw) for i in range(1, 5): for h in h_list: quad_anal = self.QuadAnalDF[h, i] if norm: quad_anal /= uv for j in range(len(coord_list)): if x_vals is None and prop_dir == 'x': quad_anal_index = np.zeros(self.shape[1]) for k in range(self.shape[1]): quad_anal_index[k] = quad_anal[index[k][j], k] else: quad_anal_index = quad_anal[index[ j], :] if prop_dir == 'x' else quad_anal[:, index[j]].T ax[i - 1, j].cplot(coords, quad_anal_index, label=r"$h=%.5g$" % h, **line_kw) ax[i - 1, j].set_xlabel(r"$%s/\delta$" % prop_dir) # ,fontsize=20) ax[i - 1, j].set_ylabel(r"$Q%d$" % i) # ,fontsize=20) ax[i - 1, j].set_title(r"$%s=%.5g$" % (unit, coord_list[j]), loc='left') # ,fontsize=16) ncol = 4 if len(h_list) > 3 else len(h_list) ax[0, 0].clegend(vertical=False, ncol=ncol) ax[0, 0].get_gridspec().tight_layout(fig) fig.tight_layout() return fig, ax
def plot_autocorr_line(self, comp, axis_vals, y_vals, y_mode='half_channel', norm_xval=None, norm=True, fig=None, ax=None, **kwargs): if not comp in ('x', 'z'): msg = f"comp must be the string 'x' or 'z' not {comp} " axis_vals = misc_utils.check_list_vals(axis_vals) y_vals = misc_utils.check_list_vals(y_vals) axis_index = [ self._avg_data._return_index(x) for x in axis_vals ] #CT.coord_index_calc(self._meta_data.CoordDF,'x',axis_vals) Ruu = self.autocorrDF[comp].copy() shape = Ruu.shape if norm: Ruu_0 = Ruu[0].copy() for i in range(shape[0]): Ruu[i] /= Ruu_0 kwargs = cplt.update_subplots_kw(kwargs, figsize=[10, 5 * len(y_vals)]) fig, ax = cplt.create_fig_ax_without_squeeze(len(y_vals), fig=fig, ax=ax, **kwargs) if norm_xval is not None: if norm_xval == 0: norm_xval = np.amin(self._avg_data._return_xaxis()) x_axis_vals = [norm_xval] * len(axis_vals) else: x_axis_vals = axis_vals y_index_axis_vals = indexing.y_coord_index_norm( self._avg_data, y_vals, x_axis_vals, y_mode) coord = self._meta_data.CoordDF[comp][:shape[0]] for j, _ in enumerate(y_vals): for i, _ in enumerate(axis_index): ax[j].cplot(coord, Ruu[:, y_index_axis_vals[i][j], axis_index[i]]) #creating title label y_unit=r"y" if y_mode=='half_channel' \ else r"\delta_u" if y_mode=='disp_thickness' \ else r"\theta" if y_mode=='mom_thickness' \ else r"y^+" if norm_xval is None else r"y^{+0}" ax[j].set_title(r"$%s=%.3g$" % (y_unit, y_vals[j]), loc='left') ax[j].set_ylabel(r"$R_{%s%s}$" % self.comp) ax[j].set_xlabel(r"$%s/\delta$" % comp) return fig, ax
def plot_vorticity_contour(self,comp,plane,axis_vals,PhyTime=None,avg_data=None,x_split_list=None,y_mode='half_channel',pcolor_kw=None,fig=None,ax=None,**kwargs): """ Creates a contour plot of the vorticity contour Parameters ---------- comp : str Component of the vorticity to be extracted e.g. "x" for \omega_z, the spanwise vorticity plane : str, optional Plane for the contour plot for example "xz" or "rtheta" (for pipes), by default 'xz' axis_vals : int, float (or list of them) locations in the third axis to be plotted PhyTime : float, optional Physical time to be plotted, None can be used if the instance contains a single time, by default None avg_data : CHAPSim_AVG Used to aid plotting certain locations using in the y direction if wall units are used for example x_split_list : list, optional Separating domain into different streamwise lengths useful if the domain is much longer than its width, by default None y_mode : str, optional Only relevant if the xz plane is being used. The y value can be selected using a number of different normalisations, by default 'wall' fig : %(fig)s, optional Pre-existing figure, by default None ax : %(ax)s, optional Pre-existing axes, by default None Returns ------- %(fig)s, %(ax)s output figure and axes objects """ VorticityDF = self.vorticity_calc(PhyTime=PhyTime) plane = self.Domain.out_to_in(plane) axis_vals = misc_utils.check_list_vals(axis_vals) PhyTime = self.check_PhyTime(PhyTime) plane, coord = VorticityDF.CoordDF.check_plane(plane) if coord == 'y': if avg_data is None: msg = "If the xz plane is selected the avg_data variable must be set" raise TypeError(msg) axis_vals = indexing.ycoords_from_coords(avg_data,axis_vals,mode=y_mode)[0] int_vals = indexing.ycoords_from_norm_coords(avg_data,axis_vals,mode=y_mode)[0] else: int_vals = axis_vals = indexing.true_coords_from_coords(self.CoordDF,coord,axis_vals) x_size, z_size = VorticityDF.get_unit_figsize(plane) figsize=[x_size,z_size*len(axis_vals)] axes_output = True if isinstance(ax,mpl.axes.Axes) else False kwargs = cplt.update_subplots_kw(kwargs,figsize=figsize) fig, ax = cplt.create_fig_ax_without_squeeze(len(axis_vals),fig=fig,ax=ax,**kwargs) title_symbol = misc_utils.get_title_symbol(coord,y_mode,False) for i,val in enumerate(int_vals): fig, ax1 = VorticityDF.plot_contour(comp,plane,val,time=PhyTime,fig=fig,ax=ax[i],pcolor_kw=pcolor_kw) ax1.axes.set_xlabel(r"$%s/\delta$" % plane[0]) ax1.axes.set_ylabel(r"$%s/\delta$" % plane[1]) ax1.axes.set_title(r"$%s=%.2g$"%(title_symbol,axis_vals[i]),loc='right') ax1.axes.set_title(r"$t^*=%s$"%PhyTime,loc='left') cbar=fig.colorbar(ax1,ax=ax[i]) cbar.set_label(r"$%s^\prime$"%comp) ax[i]=ax1 ax[i].axes.set_aspect('equal') if axes_output: return fig, ax[0] else: return fig, ax
def autocorr_contour_y(self, comp, axis_vals, Y_plus=False, Y_plus_0=False, Y_plus_max=None, norm=True, show_positive=True, fig=None, ax=None, pcolor_kw=None, **kwargs): if comp not in ('x', 'z'): raise ValueError(" Variable `comp' must eiher be 'x' or 'z'\n") if not hasattr(axis_vals, '__iter__'): axis_vals = [axis_vals] axis_index = [ self._avg_data._return_index(x) for x in axis_vals ] #CT.coord_index_calc(self._meta_data.CoordDF,'x',axis_vals) shape = self.autocorrDF[comp].shape Ruu = self.autocorrDF[comp][:, :, axis_index].copy() if norm: Ruu_0 = Ruu[0].copy() for i in range(shape[0]): Ruu[i] /= Ruu_0 kwargs = cplt.update_subplots_kw(kwargs, figsize=[10, 4 * len(axis_vals)]) fig, ax = cplt.create_fig_ax_without_squeeze(len(axis_vals), fig=fig, ax=ax, **kwargs) pcolor_kw = cplt.update_pcolor_kw(pcolor_kw) max_val = -np.float('inf') min_val = np.float('inf') for i, _ in enumerate(axis_vals): y_coord = self._meta_data.CoordDF['y'].copy() coord = self._meta_data.CoordDF[comp].copy()[:shape[0]] if Y_plus: avg_time = self._avg_data.flow_AVGDF.index[0][0] _, delta_v_star = self._avg_data.wall_unit_calc(avg_time) y_coord = y_coord[:int(y_coord.size / 2)] if i == 0: Ruu = Ruu[:, :y_coord.size] if Y_plus_0: y_coord = (1 - np.abs(y_coord)) / delta_v_star[0] else: y_coord = (1 - np.abs(y_coord)) / delta_v_star[axis_index[i]] min_val = min(min_val, np.amin(np.squeeze(Ruu[:, :, i]))) max_val = max(max_val, np.amax(np.squeeze(Ruu[:, :, i]))) X, Y = np.meshgrid(coord, y_coord) ax[i] = ax[i].pcolormesh(X, Y, np.squeeze(Ruu[:, :, i]).T, **pcolor_kw) ax[i].axes.set_xlabel(r"$\Delta %s/\delta$" % comp) if Y_plus and Y_plus_0: ax[i].axes.set_ylabel(r"$Y^{+0}$") elif Y_plus and not Y_plus_0: ax[i].axes.set_ylabel(r"$Y^{+}$") else: ax[i].axes.set_ylabel(r"$y/\delta$") if Y_plus_max is not None: ax[i].axes.set_ylim(top=Y_plus_max) fig.colorbar(ax[i], ax=ax[i].axes) fig.tight_layout() for a in ax: a.set_clim(min_val, max_val) if not show_positive: for a in ax: cmap = a.get_cmap() min_val, max_val = a.get_clim() new_color = cmap(np.linspace(0, 1, 256))[::-1] new_color[-1] = np.array([1, 1, 1, 1]) a.set_cmap(mpl.colors.ListedColormap(new_color)) a.set_clim(min_val, 0) return fig, ax
def plot_vector(self,plane,axis_vals,avg_data,PhyTime=None,y_mode='half_channel',spacing=(1,1),scaling=1,fig=None,ax=None,quiver_kw=None,**kwargs): """ Create vector plot of a plane of the instantaneous flow Parameters ---------- plane : str, optional Plane for the contour plot for example "xz" or "rtheta" (for pipes), by default 'xz' axis_vals : int, float (or list of them) locations in the third axis to be plotted avg_data : CHAPSim_AVG Used to aid plotting certain locations using in the y direction if wall units are used for example PhyTime : float, optional Physical time to be plotted, None can be used if the instance contains a single time, by default None y_mode : str, optional Only relevant if the xz plane is being used. The y value can be selected using a number of different normalisations, by default 'wall' spacing : tuple, optional [description], by default (1,1) scaling : int, optional [description], by default 1 x_split_list : list, optional Separating domain into different streamwise lengths useful if the domain is much longer than its width, by default None fig : %(fig)s, optional Pre-existing figure, by default None ax : %(ax)s, optional Pre-existing axes, by default None quiver_kw : dict, optional Argument passed to matplotlib quiver plot, by default None Returns ------- %(fig)s, %(ax)s output figure and axes objects """ plane = self.Domain.out_to_in(plane) axis_vals = misc_utils.check_list_vals(axis_vals) PhyTime = self.check_PhyTime(PhyTime) plane, coord = self.InstDF.CoordDF.check_plane(plane) if coord == 'y': if avg_data is None: msg = "If the xz plane is selected the avg_data variable must be set" raise TypeError(msg) axis_vals = indexing.ycoords_from_coords(avg_data,axis_vals,mode=y_mode)[0] int_vals = indexing.ycoords_from_norm_coords(avg_data,axis_vals,mode=y_mode)[0] else: int_vals = axis_vals = indexing.true_coords_from_coords(self.CoordDF,coord,axis_vals) x_size, z_size = self.InstDF.get_unit_figsize(plane) figsize=[x_size*len(axis_vals),z_size] axes_output = True if isinstance(ax,mpl.axes.Axes) else False kwargs = cplt.update_subplots_kw(kwargs,figsize=figsize) fig, ax = cplt.create_fig_ax_without_squeeze(len(axis_vals),fig=fig,ax=ax,**kwargs) title_symbol = misc_utils.get_title_symbol(coord,y_mode,False) for i, val in enumerate(int_vals): fig, ax[i] = self.InstDF.plot_vector(plane,val,time=PhyTime,spacing=spacing,scaling=scaling, fig=fig,ax=ax[i],quiver_kw=quiver_kw) ax[i].axes.set_xlabel(r"$%s/\delta$"%slice[0]) ax[i].axes.set_ylabel(r"$%s/\delta$"%slice[1]) ax[i].axes.set_title(r"$%s = %.2g$"%(title_symbol,axis_vals[i]),loc='right') ax[i].axes.set_title(r"$t^*=%s$"%PhyTime,loc='left') if axes_output: return fig, ax[0] else: return fig, ax
def plot_mode_contour(self, comp, modes, axis_val, plane='xz', y_mode='wall', fig=None, ax=None, pcolor_kw=None, **kwargs): modes = misc_utils.check_list_vals(modes) axes_output = True if isinstance(ax, mpl.axes.Axes) else False axis_val = misc_utils.check_list_vals(axis_val) if len(axis_val) > 1: msg = "This routine can only process one slice in a single call" raise ValueError(msg) for i, mode in enumerate(modes): PODmodes = self.POD_modesDF.values[:, :, :, :, mode] POD_modeDF = cd.flowstruct3D(self._coorddata, PODmodes, index=self.POD_modesDF.index) plane, coord = POD_modeDF.CoordDF.check_plane(plane) if coord == 'y': val = indexing.ycoords_from_coords(self.avg_data, axis_val, mode=y_mode)[0][0] int_val = indexing.ycoords_from_norm_coords(self.avg_data, axis_val, mode=y_mode)[0][0] else: int_val = val = indexing.true_coords_from_coords( self.CoordDF, coord, axis_val)[0] if i == 0: x_size, z_size = POD_modeDF.get_unit_figsize(plane) figsize = [x_size, z_size * len(modes)] kwargs = cplt.update_subplots_kw(kwargs, figsize=figsize) fig, ax = cplt.create_fig_ax_without_squeeze(len(modes), fig=fig, ax=ax, **kwargs) title_symbol = misc_utils.get_title_symbol(coord, y_mode, False) fig, ax[i] = POD_modeDF.plot_contour(comp, plane, int_val, time=None, fig=fig, ax=ax[i], pcolor_kw=pcolor_kw) ax[i].axes.set_xlabel(r"$%s/\delta$" % plane[0]) ax[i].axes.set_ylabel(r"$%s/\delta$" % plane[1]) ax[i].axes.set_title(r"$%s=%.2g$" % (title_symbol, val), loc='right') ax[i].axes.set_title(r"Mode %d" % (mode + 1), loc='left') cbar = fig.colorbar(ax[i], ax=ax[i].axes) ax[i].axes.set_aspect('equal') if axes_output: return fig, ax[0] else: return fig, ax
def _budget_plot(self, PhyTime, x_list, budget_terms=None, wall_units=True, fig=None, ax=None, line_kw=None, **kwargs): u_tau_star, delta_v_star = self.avg_data._wall_unit_calc(PhyTime) budget_scale = u_tau_star**3 / delta_v_star Y_extent = int(self.avg_data.shape[0] / 2) if wall_units: Y_coords = self.avg_data._y_plus_calc(PhyTime) else: Y = np.zeros(self.avg_data.shape[::-1]) for i in range(self.avg_data.shape[1]): Y[i] = self.avg_data.CoordDF['y'] Y_coords = (1 - np.abs(Y[:, :Y_extent])) if isinstance(x_list, list): ax_size = len(x_list) else: ax_size = 1 ax_size = (int(np.ceil(ax_size / 2)), 2) if ax_size > 2 else (ax_size, 1) lower_extent = 0.2 gridspec_kw = {'bottom': lower_extent} figsize = [7 * ax_size[1], 5 * ax_size[0] + 1] kwargs = cplt.update_subplots_kw(kwargs, gridspec_kw=gridspec_kw, figsize=figsize) fig, ax = cplt.create_fig_ax_without_squeeze(*ax_size, fig=fig, ax=ax, **kwargs) ax = ax.flatten() budget_terms = self._check_terms(budget_terms) x_list = misc_utils.check_list_vals(x_list) line_kw = cplt.update_line_kw(line_kw) for i, x_loc in enumerate(x_list): for comp in budget_terms: budget_values = self.budgetDF[PhyTime, comp].copy() x = self.avg_data._return_index(x_loc) if wall_units: budget = budget_values[:Y_extent, x] / budget_scale[x] else: budget = budget_values[:Y_extent, x] if self.comp == 'uv': budget = budget * -1.0 ax[i].cplot(Y_coords[x, :].squeeze(), budget, label=comp.title(), **line_kw) if wall_units: ax[i].set_xscale('log') # ax[i].set_xlim(left=1.0) ax[i].set_xlabel(r"$y^+$") else: x_label = self.Domain.in_to_out(r"$y/\delta$") ax[i].set_xlabel(x_label) if mpl.rcParams['text.usetex'] == True: ax[i].set_ylabel(r"Loss\ \ \ \ \ \ \ \ Gain") else: ax[i].set_ylabel(r"Loss Gain") return fig, ax
def plot_spectra(self, comp, axis_vals, y_vals, y_mode='half_channel', norm_xval=None, fig=None, ax=None, **kwargs): if not comp in ('x', 'z'): raise ValueError(" Variable `comp' must eiher be 'x' or 'z'\n") axis_vals = misc_utils.check_list_vals(axis_vals) y_vals = misc_utils.check_list_vals(y_vals) axis_index = [ self._avg_data._return_index(x) for x in axis_vals ] #CT.coord_index_calc(self._meta_data.CoordDF,'x',axis_vals) Ruu = self.autocorrDF[comp] shape = Ruu.shape kwargs = cplt.update_subplots_kw(kwargs, figsize=[10, 5 * len(y_vals)]) fig, ax = cplt.create_fig_ax_without_squeeze(len(y_vals), fig=fig, ax=ax, **kwargs) if norm_xval is not None: if norm_xval == 0: x_axis_vals = [np.amin(self._avg_data._return_xaxis()) ] * len(axis_vals) else: x_axis_vals = [norm_xval] * len(axis_vals) else: x_axis_vals = axis_vals coord = self._meta_data.CoordDF[comp][:shape[0]] y_index_axis_vals = indexing.y_coord_index_norm( self._avg_data, y_vals, x_axis_vals, y_mode) for j, _ in enumerate(y_vals): for i, _ in enumerate(axis_index): wavenumber_spectra = fft.rfft(Ruu[:, y_index_axis_vals[i][j], axis_index[i]].squeeze()) delta_comp = coord[1] - coord[0] comp_size = Ruu[:, y_index_axis_vals[i][j], axis_index[i]].size wavenumber_comp = 2 * np.pi * fft.rfftfreq( comp_size, delta_comp) y_unit=r"y" if y_mode=='half_channel' \ else r"\delta_u" if y_mode=='disp_thickness' \ else r"\theta" if y_mode=='mom_thickness' \ else r"y^+" if norm_xval !=0 else r"y^{+0}" ax[j].cplot(wavenumber_comp, 2 * np.abs(wavenumber_spectra)) ax[j].set_title(r"$%s=%.3g$" % (y_unit, y_vals[j]), loc='left') string = (ord(self.comp[0]) - ord('u') + 1, ord(self.comp[1]) - ord('u') + 1, comp) ax[j].set_ylabel(r"$E_{%d%d}(\kappa_%s)$" % string) ax[j].set_xlabel(r"$\kappa_%s$" % comp) return fig, ax