def main(): # Fetch folders for code structure folder = folders(folderScripts=os.path.dirname(os.path.realpath(__file__)), folderData="/mnt/f/Desktop/LES_Data") customLegend(folder=folder.outputs)
def main(): # Fetch folders for code structure folder = folders(folderScripts=os.path.dirname(os.path.realpath(__file__)), folderData="/mnt/f/Desktop/LES_Data") # Get Large Eddy Simulation data les = getLesData(os.path.join(folder.data, "mov0235_ALL_01-_.nc")) # Create plots for each snapshot in time for n in range(len(les.t)): folderTime = os.path.join(folder.outputs, "timestep_{}".format(n)) if not os.path.isdir(folderTime): os.makedirs(folderTime) snapshot = les.data[n] # Which layers of the 3D data set do we want to plot? imagesIndices = range(0, min(len(snapshot.x), len(snapshot.y)), 10) # Plot slices at fixed locations on the y-axis for j in imagesIndices: layer = snapshot.y[j] * 1e-3 title = "y = {:.2f}km (id={})".format(layer, j + 1) print "XZ layer {} ({})".format(j + 1, title) # Plot with only clouds plotThermalContour(snapshot.x * 1e-3, snapshot.z * 1e-3, snapshot.ql.field[:, j, :], showMesh=True, id="{}_xz_mesh+cloud".format(j), title=title, xlabel="x (km)", dpi=500, folder=folderTime) # Plot slices at fixed locations on the x-axis for i in imagesIndices: layer = snapshot.x[i] * 1e-3 title = "x = {:.2f}km (id={})".format(layer, i + 1) print "YZ layer {} ({})".format(i + 1, title) # Plot with only clouds plotThermalContour(snapshot.y * 1e-3, snapshot.z * 1e-3, snapshot.ql.field[:, :, i], showMesh=True, id="{}_yz_mesh+cloud".format(i), title=title, xlabel="y (km)", dpi=500, folder=folderTime)
def addThetaBackground(folderData="/mnt/c/MONC_ARM", indicatorMONC="plume", timesMONC=[13800]): folder = folders(folderScripts=os.path.dirname(os.path.realpath(__file__)), folderData=folderData) files = getFilesInFolder(folder.data1d, extension=".nc") dataAll = {} for file in files: print(f"\nReading file: {file}") # Get Large Eddy Simulation data data = netCDF4.Dataset(file) les = lesDataMonc1D(data) # Merge dictionaries dataAll and les dataAll = {**dataAll, **les.data} # Now update the data sets for n, t in enumerate(timesMONC): print("Processing timestep {} of {}".format(n + 1, len(timesMONC))) # filenameTheta = os.path.join(folder.monc, "time_{}".format(timesMONC[n]), "profilesMean", indicatorMONC, "z_th.npz") filenameTheta = os.path.join(folder.monc, "time_{}".format(timesMONC[n]), "profilesMean", indicatorMONC, "z_th_uncorrected.npz") dataTheta = np.load(filenameTheta) dataTheta = {key: dataTheta[key] for key in dataTheta} # Save old profiles for safe-keeping np.savez(filenameTheta.replace("z_th.npz", "z_th_uncorrected.npz"), **dataTheta) # Add the missing mean profiles to the vertical distributions fields = [ "av", "fluid1", "fluid2", "fluid1Min", "fluid1Max", "fluid2Min", "fluid2Max" ] thetaMoncMean = dataTheta["av"] for field in fields: dataTheta[field] = dataAll[float( t)]["theta_mean"] - thetaMoncMean + dataTheta[field] np.savez(filenameTheta.replace("z_th_uncorrected.npz", "z_th.npz"), **dataTheta)
def compareLEMvsMONC( indicatorLEM = "plume", indicatorMONC = "plume", timesLEM = [14000], timesMONC = [13800] ): # Fetch folders for code structure folder = folders( folderScripts = os.path.dirname(os.path.realpath(__file__)) ) variables = ["ql", "qv", "theta", "u", "v", "w"] # Create plots for each snapshot in time for n in range(min(len(timesLEM), len(timesMONC))): print("Processing timestep {} of {}".format(n+1, min(len(timesLEM), len(timesMONC)))) folderTimeLEM = os.path.join(folder.lem, "time_{}".format(timesLEM[n]), "profilesMean", indicatorLEM) folderTimeMONC = os.path.join(folder.monc, "time_{}".format(timesMONC[n]), "profilesMean", indicatorMONC) folderTime = os.path.join(folder.outputs, "lem_{}_monc_{}".format(timesLEM[n], timesMONC[n]), "profilesMean") ''' Plot comparisons of vertical profiles ''' plotVolumeFractionComparison( folderTimeLEM, folderTimeMONC, title="Volume fraction", folder=folderTime ) plotVerticalProfileComparison( "u", folderTimeLEM, folderTimeMONC, title="Horizontal velocity", xlabel="u (m/s)", folder=folderTime, plotZero=True ) plotVerticalProfileComparison( "v", folderTimeLEM, folderTimeMONC, title="Horizontal velocity", xlabel="v (m/s)", folder=folderTime, plotZero=True ) plotVerticalProfileComparison( "w", folderTimeLEM, folderTimeMONC, title="Vertical velocity", xlabel="w (m/s)", folder=folderTime, plotZero=True ) plotVerticalProfileComparison( "theta", folderTimeLEM, folderTimeMONC, title="Potential temperature", xlabel="$\\theta$ (K)", folder=folderTime, plotZero=True ) plotVerticalProfileComparison( "qv", folderTimeLEM, folderTimeMONC, title="Water vapour", xlabel="$q_v$ (kg/kg)", folder=folderTime, plotZero=True ) plotVerticalProfileComparison( "ql", folderTimeLEM, folderTimeMONC, title="Liquid water", xlabel="$q_l$ (kg/kg)", folder=folderTime, plotZero=True )
def lesCloudContours(id="LEM", caseStudy="ARM", indicatorFunction="plume", netcdfFile=None, interval=1, generateGif=False, greyscale=False, plotCloud=False, plotThermals=True, plotVelocity=False, plotAll=False): ''' Plot cross sections of clouds and their underlying structures. :param id: The simulation source type, set to either "ARM" or "MONC", str. :param caseStudy: The name of the case study to be plot, str. :param indicatorFunction: The type of structure to overlay onto the cloud, str. :param netcdfFile: Specify the netcdf file to open (all files processed if none selected), str. :param interval: Gap between layers to be plotted (1 means every layer plotted), int. :param generateGif: Compose all generated images into an animation cycling through the layers, bool. :param plotCloud: If True generate plot showing only the clouds, bool. :param plotThermals: If True generate plot showing cloud and the chosen indicatorFunction, bool. :param plotVelocity: If True generate plot showing cloud and the vertical velocity, bool. :param plotAll: If True generate plot showing all the features above, bool. ''' # Fetch folders for code structure if id == "LEM": folder = folders(id=id, folderScripts=os.path.dirname( os.path.realpath(__file__)), folderData="/mnt/f/Desktop/LES_Data") elif id == "MONC": folder = folders(id=f"{id}_{caseStudy}", folderScripts=os.path.dirname( os.path.realpath(__file__)), folderData=f"/mnt/c/{id}_{caseStudy}") else: raise ValueError(f"id {id} is not valid. Use LEM or MONC.") if netcdfFile: files = [os.path.join(folder.data, netcdfFile)] else: # Find all NetCFD files in files = getFilesInFolder(folder.data, extension=".nc") for file in files: print(f"\nProcessing file: {file}") # Get Large Eddy Simulation data les = getLesData(file, id=id, indicatorFunction=indicatorFunction) # Create plots for each snapshot in time for n in range(len(les.t)): print("\nProcessing timestep {} (t = {:.2f}hrs, t = {:.1f}s)". format(n + 1, float(les.t[n]) / 3600., float(les.t[n]))) folderTime = os.path.join(folder.outputs, "time_{}".format(int(les.t[n]))) if not os.path.isdir(folderTime): os.makedirs(folderTime) snapshot = les.data[n] # Which layers of the 3D data set do we want to plot? imagesIndices = range(0, min(len(snapshot.x), len(snapshot.y)), interval) '''# Plot slices at fixed locations on the z-axis for k in range(0, len(snapshot.z), 10): layer = snapshot.z[k]*1e-3 title = "z = {:.2f}km (id={})".format(layer, k+1) print "XY layer {} ({})".format(k+1, title) plotThermalContour( snapshot.x*1e-3, snapshot.y*1e-3, snapshot.ql.field[k,:,:], id="{}_xy_cloud+updraft".format(k), title=title, xlabel="x (km)", ylabel="y (km)", xlim=[-10.,10.], ylim=[-10.,10.], velocityVectorsOnly = True, folder=folderTime, I2=snapshot.I2.field[k,:,:], u=(snapshot.u.field-0*np.mean(snapshot.u.av))[k,:,:], w=(snapshot.v.field-0*np.mean(snapshot.v.av))[k,:,:] )''' # Plot slices at fixed locations on the y-axis for j in imagesIndices: layer = snapshot.y[j] * 1e-3 title = f"t = {float(les.t[n])/3600:.2f} hours, y = {layer:.2f} km" print(f"XZ layer {j+1} ({title})") # Plot with only clouds if plotCloud: plotThermalContour(snapshot.x * 1e-3, snapshot.z * 1e-3, snapshot.ql.field[:, j, :], id="{}_xz_cloud".format(j), title=title, xlabel="x (km)", folder=folderTime, greyscale=greyscale) # Plot including structure of thermals below clouds if plotThermals: plotThermalContour( snapshot.x * 1e-3, snapshot.z * 1e-3, snapshot.ql.field[:, j, :], id="{}_xz_cloud+thermal".format(j), # title=title, xlabel="x (km)", folder=folderTime, I2=snapshot.I2.field[:, j, :], greyscale=greyscale) # Plot including regions of positive vertical velocity (updrafts) if plotVelocity: plotThermalContour( snapshot.x * 1e-3, snapshot.z * 1e-3, snapshot.ql.field[:, j, :], id="{}_xz_cloud+updraft".format(j), title=title, xlabel="x (km)", folder=folderTime, # u=(snapshot.v.field-snapshot.v.av[:,None,None])[:,j,:], w=snapshot.w.field[:, j, :], greyscale=greyscale) # Plot including clouds, structure of thermals and vertical velocity if plotAll: plotThermalContour( snapshot.x * 1e-3, snapshot.z * 1e-3, snapshot.ql.field[:, j, :], id="{}_xz_cloud+thermal+updraft".format(j), title=title, xlabel="x (km)", folder=folderTime, I2=snapshot.I2.field[:, j, :], w=snapshot.w.field[:, j, :], greyscale=greyscale) # Remove les data to clear memory totalTimesteps = len(les.t) del les del snapshot # Create gif animations for generated plots if generateGif: for n in range(totalTimesteps): folderTime = os.path.join(folder.outputs, "timestep_{}".format(n)) imageListContourXZ = [] for k in imagesIndices: print(k) imageListContourXZ = [] imageListContourYZ = [] imageListContourXZ.append( os.path.join(os.path.join(folderTime, "contourCloud"), "contour_{}_xz_cloud.png".format(k))) imageListContourXZ.append( os.path.join( os.path.join(folderTime, "contourCloud"), "contour_{}_xz_cloud+thermal.png".format(k))) imageListContourXZ.append( os.path.join( os.path.join(folderTime, "contourCloud"), "contour_{}_xz_cloud+thermal+updraft.png".format( k))) makeGif("contour_{}_xz.gif".format(k), imageListContourXZ, folder=folderTime, delay=200)
def cloudFractionContour(generateGif=False, id="LEM", caseStudy="ARM", indicatorFunction="basic", netcdfFile=None): # Fetch folders for code structure if id == "LEM": folder = folders( id = id, folderScripts = os.path.dirname(os.path.realpath(__file__)), folderData = "/mnt/f/Desktop/LES_Data" ) elif id == "MONC": folder = folders( id = f"{id}_{caseStudy}", folderScripts = os.path.dirname(os.path.realpath(__file__)), folderData = f"/mnt/c/{id}_{caseStudy}" ) else: raise ValueError(f"id {id} is not valid.") if netcdfFile: files = [os.path.join(folder.data, netcdfFile)] else: # Get all available NetCFD files files = getFilesInFolder(folder.data, extension=".nc") times = [] cloudTops = {} cloudBases = {} cloudCovers = {} cloudCovers1 = {} cloudCovers2 = {} cloudFractions = {} cloudFractions1 = {} cloudFractions2 = {} cloudFractions1sigma1 = {} cloudFractions2sigma2 = {} for i,file in enumerate(files): print(f"\nProcessing 3D file: {file} (file {i+1} of {len(files)})") # Get Large Eddy Simulation data les = getLesData( file, id = id, indicatorFunction = indicatorFunction ) # Create plots for each snapshot in time for n in range(len(les.t)): print("\nProcessing timestep {} (t = {:.2f}hrs, t = {:.1f}s)".format(n+1, float(les.t[n])/3600., float(les.t[n]))) time = int(les.t[n]) folderTime = os.path.join(folder.outputs, f"time_{time}") if not os.path.isdir(folderTime): os.makedirs(folderTime) snapshot = les.data[n] z = snapshot.z cloud = snapshot.ql.field > 1e-5 cloudz = np.max(snapshot.ql.field, axis=snapshot.ql.axisXY) > 1e-5 cloudFraction = horizontalAverage(cloud, axis=snapshot.ql.axisXY) cloudFraction1 = conditionalAverage(cloud, np.invert(snapshot.I2.field), axis=snapshot.ql.axisXY) cloudFraction2 = conditionalAverage(cloud, snapshot.I2.field, axis=snapshot.ql.axisXY) cloudFraction1sigma1 = cloudFraction1*(1-snapshot.I2.av) cloudFraction2sigma2 = cloudFraction2*snapshot.I2.av times.append(time) if not True in cloudz: cloudTops[time] = 0. cloudBases[time] = 0. else: cloudTops[time] = np.max(z[cloudz]) cloudBases[time] = np.min(z[cloudz]) cloudCovers[time] = calculateCloudCover(cloud, axis=(snapshot.keys.zi)) cloudCovers1[time] = calculateCloudCover(cloud * np.invert(snapshot.I2.field), axis=(snapshot.keys.zi)) cloudCovers2[time] = calculateCloudCover(cloud * snapshot.I2.field, axis=(snapshot.keys.zi)) cloudFractions[time] = cloudFraction cloudFractions1[time] = cloudFraction1 cloudFractions2[time] = cloudFraction2 cloudFractions1sigma1[time] = cloudFraction1sigma1 cloudFractions2sigma2[time] = cloudFraction2sigma2 print("Cloud cover: {:.3f}".format(cloudCovers[time])) print("Cloud base: {:.1f}m".format(cloudBases[time])) print("Cloud top: {:.1f}m".format(cloudTops[time])) ''' plotCloudFraction( snapshot.z, cloudFraction, id = "all", folder = folderTime ) plotCloudFraction( snapshot.z, cloudFraction1, id = "1", folder = folderTime ) plotCloudFraction( snapshot.z, cloudFraction2, id = "2", folder = folderTime ) ''' del les del snapshot cloudTop = np.zeros_like(times, dtype=float) cloudBase = np.zeros_like(times, dtype=float) cloudCover = np.zeros_like(times, dtype=float) cloudCover1 = np.zeros_like(times, dtype=float) cloudCover2 = np.zeros_like(times, dtype=float) cloudFraction = np.zeros((len(cloudFractions[times[0]]), len(times))) cloudFraction1 = np.zeros((len(cloudFractions1[times[0]]), len(times))) cloudFraction2 = np.zeros((len(cloudFractions2[times[0]]), len(times))) cloudFraction1sigma1 = np.zeros((len(cloudFractions1sigma1[times[0]]), len(times))) cloudFraction2sigma2 = np.zeros((len(cloudFractions2sigma2[times[0]]), len(times))) times = sorted(times) for n in range(len(times)): time = times[n] cloudTop[n] = cloudTops[time] cloudBase[n] = cloudBases[time] cloudCover[n] = cloudCovers[time] cloudCover1[n] = cloudCovers1[time] cloudCover2[n] = cloudCovers2[time] cloudFraction[:,n] = cloudFractions[time] cloudFraction1[:,n] = cloudFractions1[time] cloudFraction2[:,n] = cloudFractions2[time] cloudFraction1sigma1[:,n] = cloudFractions1sigma1[time] cloudFraction2sigma2[:,n] = cloudFractions2sigma2[time] data = {} data["t_cloud_fraction"] = np.array(times) data["z_cloud_fraction"] = z data["cloud_top"] = cloudTop data["cloud_base"] = cloudBase data["cloud_cover"] = cloudCover data["cloud_cover1"] = cloudCover1 data["cloud_cover2"] = cloudCover2 data["cloud_fraction"] = cloudFraction data["cloud_fraction1"] = cloudFraction1 data["cloud_fraction2"] = cloudFraction2 data["cloud_fraction1_sigma1"] = cloudFraction1sigma1 data["cloud_fraction2_sigma2"] = cloudFraction2sigma2 folder = os.path.join(folder.outputs, "cloudContour") if not os.path.isdir(folder): os.makedirs(folder) savemat(os.path.join(folder, "cloud_fraction.mat"), data)
def main(): # indicatorFunction="basic" # indicatorFunction="plume" indicatorFunction = "plumeEdge" # Fetch folders for code structure folder = folders(folderScripts=os.path.dirname(os.path.realpath(__file__)), folderData="/mnt/f/Desktop/LES_Data") lesDiagnostics = getScmData(os.path.join(folder.data, "LES_transfers.mat")) for key in lesDiagnostics: print(key) # Create plots for each snapshot in time t = [8.89 * 3600] for n in range(len(t)): print("Processing timestep {} (t = {:.2f}hrs, {}s)".format( n + 1, float(t[n]) / 3600., t[n])) folderTime = os.path.join(folder.outputs, "timestep_{}".format(n)) ''' Plot comparisons of vertical profiles ''' plotVerticalProfileComparison("u", "plume", "plumeEdge", id3="plumeEdgeEntrain", id4="plumeEdgeDetrain", title="Horizontal velocity", xlabel="u (m/s)", folder=folderTime, plotZero=True) plotVerticalProfileComparison("v", "plume", "plumeEdge", id3="plumeEdgeEntrain", id4="plumeEdgeDetrain", title="Horizontal velocity", xlabel="v (m/s)", folder=folderTime, plotZero=True) plotVerticalProfileComparison("w", "plume", "plumeEdge", id3="plumeEdgeEntrain", id4="plumeEdgeDetrain", title="Vertical velocity", xlabel="w (m/s)", folder=folderTime, plotZero=True) plotVerticalProfileComparison("theta", "plume", "plumeEdge", id3="plumeEdgeEntrain", id4="plumeEdgeDetrain", title="Potential temperature", xlabel="$\\theta$ (K)", folder=folderTime, plotZero=True) plotVerticalProfileComparison("qv", "plume", "plumeEdge", id3="plumeEdgeEntrain", id4="plumeEdgeDetrain", title="Water vapour", xlabel="$q_v$ (kg/kg)", folder=folderTime, plotZero=True) plotVerticalProfileComparison("ql", "plume", "plumeEdge", id3="plumeEdgeEntrain", id4="plumeEdgeDetrain", title="Liquid water", xlabel="$q_l$ (kg/kg)", folder=folderTime, plotZero=True) ''' Plot the transferred properties during entrainment and detrainment - the b_ij coefficients ''' plotTransferredProperties("u", "plume", "plumeEdge", title="Horizontal velocity", xlabel="$b_{ij}$ for u", yMarkers=[1., 2.8], folder=folderTime, plotZero=True) plotTransferredProperties("v", "plume", "plumeEdge", title="Horizontal velocity", xlabel="$b_{ij}$ for v", yMarkers=[1., 2.8], folder=folderTime, plotZero=True) plotTransferredProperties("w", "plume", "plumeEdge", title="Vertical velocity", xlabel="$b_{ij}$ for w", yMarkers=[1., 2.8], folder=folderTime, plotZero=True) plotTransferredProperties("theta", "plume", "plumeEdge", title="Potential temperature", xlabel="$b_{ij}$ for $\\theta$", yMarkers=[1., 2.8], folder=folderTime, plotZero=True) plotTransferredProperties("qv", "plume", "plumeEdge", title="Water vapour", xlabel="$b_{ij}$ for $q_v$", yMarkers=[1., 2.8], folder=folderTime, plotZero=True) plotTransferredProperties("ql", "plume", "plumeEdge", title="Liquid water", xlabel="$b_{ij}$ for $q_l$", yMarkers=[1., 2.8], folder=folderTime, plotZero=True)
def lesVerticalProfiles(id="LEM", caseStudy="ARM", indicatorFunction="basic", netcdfFile=None, thetaMean=None): ''' Plot the vertical profiles of various fields in the Large Eddy Simulation (LES) data for comparison with Single Column Models (SCMs). :param id: The simulation source type, set to either "ARM" or "MONC", str. :param caseStudy: The name of the case study to be plot, str. :param indicatorFunction: The type of structure to overlay onto the cloud, str. :param netcdfFile: Specify the netcdf file to open (all files processed if none selected), str. :param thetaMean: Specify a background profile to add to the potential temperature, float np.ndarray. ''' # Fetch folders for code structure if id == "LEM": folder = folders(id=id, folderScripts=os.path.dirname( os.path.realpath(__file__)), folderData="/mnt/f/Desktop/LES_Data") elif id == "MONC": folder = folders(id=f"{id}_{caseStudy}", folderScripts=os.path.dirname( os.path.realpath(__file__)), folderData=f"/mnt/c/{id}_{caseStudy}") thetaMean = get1dProfiles(folder.data1d, key="theta_mean") else: raise ValueError(f"id {id} is not valid.") if netcdfFile: files = [os.path.join(folder.data, netcdfFile)] else: # Get all available NetCFD files files = getFilesInFolder(folder.data, extension=".nc") for i, file in enumerate(files): print(f"\nProcessing 3D file: {file} (file {i+1} of {len(files)})") # Get Large Eddy Simulation data les = getLesData(file, id=id, indicatorFunction=indicatorFunction, thetaMeanProfiles=thetaMean) # Create plots for each snapshot in time for n in range(len(les.t)): print("\nProcessing timestep {} (t = {:.2f}hrs, t = {:.1f}s)". format(n + 1, float(les.t[n]) / 3600., float(les.t[n]))) folderTime = os.path.join(folder.outputs, "time_{}".format(int(les.t[n]))) if not os.path.isdir(folderTime): os.makedirs(folderTime) snapshot = les.data[n] # Volume fraction of fluid 2 plotVolumeFraction(snapshot.z, snapshot.I2, folder=folderTime, id=indicatorFunction) # Mean profiles plotVerticalProfile(snapshot.z, snapshot.u, title="Horizontal velocity", xlabel="u (m/s)", folder=folderTime, id=indicatorFunction, plotZero=True) plotVerticalProfile(snapshot.z, snapshot.v, title="Horizontal velocity", xlabel="v (m/s)", folder=folderTime, id=indicatorFunction, plotZero=True) plotVerticalProfile(snapshot.z, snapshot.w, title="Vertical velocity", xlabel="w (m/s)", folder=folderTime, id=indicatorFunction, plotZero=True) plotVerticalProfile(snapshot.z, snapshot.th, title="Potential temperature", xlabel="$\\theta$ (K)", folder=folderTime, id=indicatorFunction) plotVerticalProfile(snapshot.z, snapshot.thv, title="Virtual potential temperature", xlabel="$\\theta_v$ (K)", folder=folderTime, id=indicatorFunction) plotVerticalProfile(snapshot.z, snapshot.b, title="Buoyancy", xlabel="b (m s$^2$)", folder=folderTime, id=indicatorFunction) plotVerticalProfile(snapshot.z, snapshot.q, title="Water vapour", xlabel="$q_t$ (kg/kg)", folder=folderTime, id=indicatorFunction) plotVerticalProfile(snapshot.z, snapshot.qv, title="Water vapour", xlabel="$q_v$ (kg/kg)", folder=folderTime, id=indicatorFunction) plotVerticalProfile(snapshot.z, snapshot.ql, title="Liquid water", xlabel="$q_l$ (kg/kg)", folder=folderTime, id=indicatorFunction) plotVerticalProfile(snapshot.z, snapshot.qr, title="Radioactive tracer", xlabel="$q_r$ (kg/kg)", folder=folderTime, id=indicatorFunction) # Variances plotVerticalVariances(snapshot.z, snapshot.u, title="Horizontal velocity variance", xlabel="$\\overline{u'u'}$ (m$^2$/s$^2$)", folder=folderTime, id=indicatorFunction) plotVerticalVariances(snapshot.z, snapshot.v, title="Horizontal velocity variance", xlabel="$\\overline{v'v'}$ (m$^2$/s$^2$)", folder=folderTime, id=indicatorFunction) plotVerticalVariances(snapshot.z, snapshot.w, title="Horizontal velocity variance", xlabel="$\\overline{w'w'}$ (m$^2$/s$^2$)", folder=folderTime, id=indicatorFunction) plotVerticalVariances( snapshot.z, snapshot.th, title="Potential temperature variance", xlabel="$\\overline{\\theta'\\theta'}$ (K$^2$)", folder=folderTime, id=indicatorFunction) plotVerticalVariances( snapshot.z, snapshot.thv, title="Virtual potential temperature variance", xlabel="$\\overline{\\theta_v'\\theta_v'}$ (K$^2$)", folder=folderTime, id=indicatorFunction) plotVerticalVariances(snapshot.z, snapshot.b, title="Buoyancy variance", xlabel="$\\overline{b'b'}$ (m$^2$/s$^4$)", folder=folderTime, id=indicatorFunction) plotVerticalVariances(snapshot.z, snapshot.q, title="Total moisture variance", xlabel="$\\overline{q'q'}$", folder=folderTime, id=indicatorFunction) plotVerticalVariances(snapshot.z, snapshot.qv, title="Water vapour variance", xlabel="$\\overline{q_v'q_v'}$", folder=folderTime, id=indicatorFunction) plotVerticalVariances(snapshot.z, snapshot.ql, title="Liquid water variance", xlabel="$\\overline{q_l'q_l'}$", folder=folderTime, id=indicatorFunction) # Vertical fluxes plotVerticalFluxes( snapshot.z, snapshot.u, title="Horizontal velocity fluxes", xlabel="$\\sigma_i \\overline{w'u'}$ (m$^2$/s$^2$)", folder=folderTime, id=indicatorFunction) plotVerticalFluxes( snapshot.z, snapshot.v, title="Horizontal velocity fluxes", xlabel="$\\sigma_i \\overline{w'v'}$ (m$^2$/s$^2$)", folder=folderTime, id=indicatorFunction) plotVerticalFluxes( snapshot.z, snapshot.th, title="Potential temperature fluxes", xlabel="$\\sigma_i \\overline{w'\\theta'}$ (K m/s)", folder=folderTime, id=indicatorFunction) plotVerticalFluxes( snapshot.z, snapshot.thv, title="Virtual potential temperature fluxes", xlabel="$\\sigma_i \\overline{w'\\theta_v'}$ (K m/s)", folder=folderTime, id=indicatorFunction) plotVerticalFluxes( snapshot.z, snapshot.b, title="Buoyancy fluxes", xlabel="$\\sigma_i \\overline{w'b'}$ (m$^2$/s$^3$)", folder=folderTime, id=indicatorFunction) plotVerticalFluxes( snapshot.z, snapshot.q, title="Total moisture fluxes", xlabel="$\\sigma_i \\overline{w'q'}$ (kg/kg m/s)", folder=folderTime, id=indicatorFunction) plotVerticalFluxes( snapshot.z, snapshot.qv, title="Water vapour fluxes", xlabel="$\\sigma_i \\overline{w'q_v'}$ (kg/kg m/s)", folder=folderTime, id=indicatorFunction) plotVerticalFluxes( snapshot.z, snapshot.ql, title="Liquid water fluxes", xlabel="$\\sigma_i \\overline{w'q_l'}$ (kg/kg m/s)", folder=folderTime, id=indicatorFunction)
def main(): # Fetch folders for code structure folder = folders(folderScripts=os.path.dirname(os.path.realpath(__file__)), folderData="/mnt/f/Desktop/LES_Data") # Get Large Eddy Simulation data les = getLesData(os.path.join(folder.data, "mov0235_ALL_01-_.nc")) # les = getLesData(os.path.join(folder.data, "mov0235_ALL_01-_.nc"), indicatorFunction="basic") # Create plots for each snapshot in time for n in range(len(les.t)): folderTime = os.path.join(folder.outputs, "timestep_{}".format(n)) if not os.path.isdir(folderTime): os.makedirs(folderTime) snapshot = les.data[n] # Create plots for each layer in the vertical for k in range(len(snapshot.z)): layer = snapshot.z[k] * 1e-3 title = "z = {:.2f}km (id={})".format(layer, k + 1) print "Layer {} ({:.3f}km)".format(k + 1, layer) # Histogram for vertical velocity, w plotLayerHistogram(snapshot.w, snapshot.I2, layer, k, title=title, folder=os.path.join(folderTime, snapshot.w.name)) # Histogram for potential temperature, theta plotLayerHistogram(snapshot.theta, snapshot.I2, layer, k, title=title, folder=os.path.join(folderTime, snapshot.theta.name)) # Histogram for water vapour, qv plotLayerHistogram(snapshot.qv, snapshot.I2, layer, k, title=title, folder=os.path.join(folderTime, snapshot.qv.name)) # Histogram for liquid water, ql plotLayerHistogram(snapshot.ql, snapshot.I2, layer, k, title=title, folder=os.path.join(folderTime, snapshot.ql.name)) # Remove les data to clear memory totalTimesteps = len(les.t) totalImages = min(len(snapshot.z), 150) del les del snapshot # Create gif animations for generated plots for n in range(totalTimesteps): folderTime = os.path.join(folder.outputs, "timestep_{}".format(n)) imageListW = [] imageListTheta = [] imageListQv = [] imageListQl = [] for k in range(totalImages): imageListW.append( os.path.join(os.path.join(folderTime, "w"), "histogram_w_{}.png".format(k + 1))) imageListTheta.append( os.path.join(os.path.join(folderTime, "theta"), "histogram_theta_{}.png".format(k + 1))) imageListQv.append( os.path.join(os.path.join(folderTime, "qv"), "histogram_qv_{}.png".format(k + 1))) imageListQl.append( os.path.join(os.path.join(folderTime, "ql"), "histogram_ql_{}.png".format(k + 1))) makeGif("histogram_w.gif", imageListW, folder=folderTime, delay=8) makeGif("histogram_theta.gif", imageListTheta, folder=folderTime, delay=8) makeGif("histogram_qv.gif", imageListQv, folder=folderTime, delay=8) makeGif("histogram_ql.gif", imageListQl, folder=folderTime, delay=8)
def calculateFields(id="default", gratingType="triangle", beamRadius=1.2, gaussian=True, imperfection=False, resolution=100, rangeX=[-0.55, 0.55], rangeY=[-0.55, 0.55], rangeZ=[0., 1.1], precisionCoords=4, precisionData=2): ''' Generate the acceleration and radiation profiles for a neutral atom in a Magneto-Optical Trap with one laser pointed down on a horizontal surface where a reflection grating is located. Args id: Data id used for the naming of output files gratingType: Shape of grating etches/grooves. Valid parameters are "triangle" and "square" beamRadius: The incident laser beam radius in cm. gaussian: Is the beam profile Gaussian or uniform? Boolean only. imperfection: If True, some of the laser beam will be diffracted to 0th order (reflection) resolution: Resolution of the data in all 3 axes. resolution x 2 = computation x 8. rangeX: Range of x values to be evaluated in cm. rangeY: Range of x values to be evaluated in cm. rangeZ: Range of x values to be evaluated in cm. precisionCoords: Precision of coordinate data when writen to output file. precisionData: Precision of field data when writen to output file. ''' print(f"\nGenerating fields for configuration: {id}") folder = folders(id=id, folderScripts=os.path.dirname(os.path.realpath(__file__))) # Get grating geometry and properties if gratingType == "square": gratings = makeSquareGrating() elif gratingType == "triangle": gratings = makeTriangleGrating() else: gratings = makeSquareGrating() # 3D Coordinate and Acceleration vector fields. axisX = np.linspace(rangeX[0], rangeX[1], resolution) axisY = np.linspace(rangeY[0], rangeY[1], resolution) axisZ = np.linspace(rangeZ[0], rangeZ[1], resolution) z, y, x = np.meshgrid(axisZ, axisY, axisX, indexing='ij') coords = np.stack((x, y, z), axis=-1) # Data arrays a = np.zeros(coords.shape) radPressure = np.zeros(coords.shape) waveVector = np.zeros(coords.shape) print("Generating fields from incident beam") # Compute acceleration or radiation pressure from incident laser beam. intensity = np.ones(x.shape) if gaussian == True: intensity *= np.e**(-(x**2 + y**2) / 2.) k = np.array([0., 0., -1.]) waveVector[...] = k a += acceleration(waveVector, coords, I=intensity) radPressure[...] += intensity[..., None] * waveVector # Ignore regions not within the beam radius conditionBeam = x**2 + y**2 <= beamRadius**2 a *= conditionBeam[..., None] radPressure *= conditionBeam[..., None] # Compute acceleration or radiation pressure from 0th order beam. if imperfection == True: print("Generating fields from 0th-order diffracted beam") intensity = 0.01 if gaussian == True: intensity *= np.exp(-(0.5 * x)**2) k = np.array([0., 0., 1.]) waveVector[...] = k a += acceleration(waveVector, coords, I=intensity, factor=-1.) radPressure[...] += intensity[..., None] * waveVector switch = True for grating in gratings: print("Generating fields from grating segment") if switch == True: switch = False factor = -1 else: factor = 1 # Compute acceleration or radiation pressure from kth grating 1st order beam. intensity = grating.reflectivity * grating.intensity( coords, factor, beamRadius, gaussian=gaussian) # Unit vector of diffracted beam waveVector[...] = grating.k radPressure += waveVector * intensity[..., None] a += acceleration(waveVector, coords, I=intensity, factor=-1.) # Compute acceleration or radiation pressure from kth grating 1st order beam in other direction. intensity = grating.reflectivity * grating.intensity( coords, -factor, beamRadius, gaussian=gaussian) # Unit vector of diffracted beam waveVector[...] = grating.k radPressure += waveVector * intensity[..., None] a += acceleration(waveVector, coords, I=intensity, factor=-1.) # Store the acceleration magnitude and the components of the acceleration. aMag = np.sqrt(np.sum(a * a, axis=(a.ndim - 1))) radPressureMag = np.sqrt( np.sum(radPressure * radPressure, axis=(radPressure.ndim - 1))) # Save fields for future use np.savez_compressed( os.path.join(folder.outputs, "fieldData.npz"), id=id, gratingType=gratingType, beamRadius=beamRadius, gaussian=gaussian, imperfection=imperfection, resolution=resolution, rangeX=rangeX, rangeY=rangeY, rangeZ=rangeZ, axisX=axisX, axisY=axisY, axisZ=axisZ, x=x.round(decimals=precisionCoords), y=y.round(decimals=precisionCoords), z=z.round(decimals=precisionCoords), a=a.round(decimals=precisionData), aMag=aMag.round(decimals=precisionData), radPressure=radPressure.round(decimals=precisionData), radPressureMag=radPressureMag.round(decimals=precisionData))
def main(): # indicatorFunction="basic" # indicatorFunction="plume" indicatorFunction = "plumeEdge" # Fetch folders for code structure folder = folders(folderScripts=os.path.dirname(os.path.realpath(__file__)), folderData="/mnt/f/Desktop/LES_Data") lesDiagnostics = getScmData(os.path.join(folder.data, "LES_transfers.mat")) for key in lesDiagnostics: print(key) # Create plots for each snapshot in time t = [8.89 * 3600] for n in range(len(t)): print("Processing timestep {} (t = {:.2f}hrs, {}s)".format( n + 1, float(t[n]) / 3600., t[n])) folderTime = os.path.join(folder.outputs, "timestep_{}".format(n)) id = "particlesEntrainDetrain" folderVertical = os.path.join(folderTime, "profilesMean") if id != "": folderVertical = os.path.join(folderVertical, id) if not os.path.isdir(folderVertical): os.makedirs(folderVertical) # Save vertical profiles for future use indexTime = np.argmin(np.abs(lesDiagnostics["times_t"][0] - t[n])) print("Time") print(indexTime) print(lesDiagnostics["times_t"][0][indexTime]) np.savez(os.path.join(folderVertical, "z_profile_w.npz"), z=lesDiagnostics["z_lev"][0][:-1] / 1000., fluid1=lesDiagnostics["w_hat_up"][:, indexTime], fluid2=lesDiagnostics["w_det_up"][:, indexTime], fluid1Std=0 * lesDiagnostics["w_hat_up"][:, indexTime], fluid2Std=0 * lesDiagnostics["w_det_up"][:, indexTime], fluid1Min=np.min(lesDiagnostics["w_hat_up"][:, indexTime]), fluid1Max=np.max(lesDiagnostics["w_hat_up"][:, indexTime]), fluid2Min=np.min(lesDiagnostics["w_det_up"][:, indexTime]), fluid2Max=np.max(lesDiagnostics["w_det_up"][:, indexTime])) np.savez(os.path.join(folderVertical, "z_profile_qv.npz"), z=lesDiagnostics["z_lev"][0][:-1] / 1000., fluid1=lesDiagnostics["qv_hat_up"][:, indexTime], fluid2=lesDiagnostics["qv_det_up"][:, indexTime], fluid1Std=0 * lesDiagnostics["qv_hat_up"][:, indexTime], fluid2Std=0 * lesDiagnostics["qv_det_up"][:, indexTime], fluid1Min=np.min(lesDiagnostics["qv_hat_up"][:, indexTime]), fluid1Max=np.max(lesDiagnostics["qv_hat_up"][:, indexTime]), fluid2Min=np.min(lesDiagnostics["qv_det_up"][:, indexTime]), fluid2Max=np.max(lesDiagnostics["qv_det_up"][:, indexTime])) np.savez(os.path.join(folderVertical, "z_profile_theta.npz"), z=lesDiagnostics["z_lev"][0][:-1] / 1000., fluid1=lesDiagnostics["th_hat_up"][:, indexTime], fluid2=lesDiagnostics["th_det_up"][:, indexTime], fluid1Std=0 * lesDiagnostics["th_hat_up"][:, indexTime], fluid2Std=0 * lesDiagnostics["th_det_up"][:, indexTime], fluid1Min=np.min(lesDiagnostics["th_hat_up"][:, indexTime]), fluid1Max=np.max(lesDiagnostics["th_hat_up"][:, indexTime]), fluid2Min=np.min(lesDiagnostics["th_det_up"][:, indexTime]), fluid2Max=np.max(lesDiagnostics["th_det_up"][:, indexTime])) plotVerticalProfileComparison("w", "plume", "particlesEntrainDetrain", title="Vertical velocity", xlabel="w (m/s)", folder=folderTime, plotZero=True) plotVerticalProfileComparison("qv", "plume", "particlesEntrainDetrain", title="Water vapour", xlabel="$q_v$", folder=folderTime, plotZero=True) # plotVerticalProfileComparison( # "theta", "plume", "particlesEntrainDetrain", # title="Potential Temperature", # xlabel="$\\theta$ (K)", # folder=folderTime, # plotZero=True # ) plotTransferredProperties("w", "plume", "particlesEntrainDetrain", title="Vertical velocity", xlabel="$b_{ij}$ for w", yMarkers=[1., 2.8], folder=folderTime, plotZero=True) plotTransferredProperties("qv", "plume", "particlesEntrainDetrain", title="Water vapour", xlabel="$b_{ij}$ for $q_v$", yMarkers=[1., 2.8], folder=folderTime, plotZero=True) indexTime = np.argmin(np.abs(lesDiagnostics["times_t"][0] - t[n])) zLes = lesDiagnostics["z_lev"][0][:-1] / 1000. w2Les = lesDiagnostics["w_up"][:, indexTime] w12Les = lesDiagnostics["w_det_up"][:, indexTime] w21Les = lesDiagnostics["w_hat_up"][:, indexTime] th2Les = lesDiagnostics["th_up"][:, indexTime] th12Les = lesDiagnostics["th_det_up"][:, indexTime] th21Les = lesDiagnostics["th_hat_up"][:, indexTime] qv2Les = lesDiagnostics["qv_up"][:, indexTime] qv12Les = lesDiagnostics["qv_det_up"][:, indexTime] qv21Les = lesDiagnostics["qv_hat_up"][:, indexTime] plotVerticalProfileComparison( "w", "plume", "plumeEdge", id3="plumeEdgeEntrain", id4="plumeEdgeDetrain", title="Vertical velocity", xlabel="w (m/s)", folder=folderTime, plotZero=True, # additionalLines=[[w12Les,zLes,"r"],[w21Les,zLes,"b"]] # additionalLines=[[w2Les,zLes,"k"]] ) plotVerticalProfileComparison( "theta", "plume", "plumeEdge", id3="plumeEdgeEntrain", id4="plumeEdgeDetrain", title="Potential temperature", xlabel="$\\theta$ (K)", folder=folderTime, plotZero=True, additionalLines=[[th12Les, zLes, "k"], [th21Les, zLes, "#888888"]]) plotVerticalProfileComparison("qv", "plume", "plumeEdge", id3="plumeEdgeEntrain", id4="plumeEdgeDetrain", title="Water vapour", xlabel="$q_v$ (kg/kg)", folder=folderTime, plotZero=True, additionalLines=[[qv12Les, zLes, "r"], [qv21Les, zLes, "b"]])
def simulateAtoms(id="default"): ''' Generate plots for the acceleration and radiation profiles for a neutral atom in a Magneto-Optical Trap with one laser pointed down on a horizontal surface where a reflection grating is located. NOTE: plotContour must be run before using plotFields Args id: Data id used for the input data filename and the output files ''' print(f"\nPlotting fields for configuration: {id}") folder = folders(id=id, folderScripts=os.path.dirname(os.path.realpath(__file__))) # Save fields for future use data = np.load(os.path.join(folder.outputs, "fieldData.npz")) x = data["x"] y = data["y"] z = data["z"] a = data["a"] aMag = data["aMag"] axisX = data["axisX"] axisY = data["axisY"] axisZ = data["axisZ"] coords = np.stack((x, y, z), axis=-1) # Generate particles particles = [] nParticles = 50 for i in range(nParticles): particles.append( particle([ 0.5 * random.uniform(data["axisX"][0], data["axisX"][-1]), 0.5 * random.uniform(data["axisY"][0], data["axisY"][-1]), random.uniform(data["axisZ"][0], data["axisZ"][-1]) ], [0, 0, 0], dragCoefficient=10.)) timestep = 5e-4 timesteps = 500 for i in range(nParticles): print("Simulating trajectory of particle {}".format(i + 1)) for n in range(timesteps): indexX = np.argmin(np.abs(axisX - particles[i].position[0])) indexY = np.argmin(np.abs(axisY - particles[i].position[1])) indexZ = np.argmin(np.abs(axisZ - particles[i].position[2])) acceleration = a[indexZ][indexY][indexX] particles[i].move(acceleration, timestep) # Generate 3D trajectory plots fig = plt.figure() ax = plt.axes(projection='3d') # Draw grating chip xGrating = [-1., -1., 1., 1.] yGrating = [-1., 1., 1., -1.] zGrating = [0., 0., 0., 0.] verts = [list(zip(xGrating, yGrating, zGrating))] poly = Poly3DCollection(verts, facecolors=[[0.5, 0.5, 0.5, 1.]]) poly.set_sort_zpos(50) ax.add_collection3d(poly) # Draw laser radius theta = np.linspace(0, 2 * np.pi, 100) radius = 1.2 xLaser = radius * np.cos(theta) yLaser = radius * np.sin(theta) zLaser = np.zeros_like(xLaser) + 0.01 verts = [list(zip(xLaser, yLaser, zLaser))] poly = Poly3DCollection(verts, facecolors=[[1., 0., 0., 0.5]]) poly.set_sort_zpos(100) ax.add_collection3d(poly) # Highlight region with weakest force-field (where particles should converge to) # cutOff = np.min(aMag) + 0.01*(np.mean(aMag)-np.min(aMag)) # condition = aMag < cutOff # ax.plot(x[condition], y[condition], z[condition], ".", color="#888888") # Draw trajectories for i in range(nParticles): pos = np.array(particles[i].positions) zorder = 10000 # Deal with particles that have gone through the ground if np.min(pos[:, 2]) < 0.: pos[:, 2] = np.maximum(pos[:, 2], 0 * pos[:, 2]) ax.plot(pos[..., 0], pos[..., 1], pos[..., 2], zorder=zorder) ax.plot(pos[..., 0][-1], pos[..., 1][-1], pos[..., 2][-1], "ko", zorder=zorder) ax.set_xlim([axisX[0], axisX[-1]]) ax.set_ylim([axisY[0], axisY[-1]]) ax.set_zlim([axisZ[0], axisZ[-1]]) ax.set_xlabel("x (cm)") ax.set_ylabel("y (cm)") ax.set_zlabel("z (cm)") # Save images from different perspectives for i in np.linspace(0, 1, 25): elevation = 90 * i angle = 90 + 360 * i ax.view_init(elev=elevation, azim=angle) plt.savefig(os.path.join( folder.outputs, "trajectories_{}_{}.png".format(id, int(360 * i))), dpi=200) plt.close()
def prepareData(indicator="plume", id="MONC", caseStudy="ARM", times=[30000], cloudData=True): # Fetch folders for code structure folder = folders(folderScripts=os.path.dirname(os.path.realpath(__file__))) variables = ["sigma", "q", "ql", "qv", "th", "thv", "b", "u", "v", "w"] # variables = ["ql", "qv", "th", "u", "w"] dataAll = dict(times=[]) # dataAll = dict(LES_times=times) # Create plots for each snapshot in time for i, t in enumerate(times): print("Processing t={}s (timestep {} of {})".format( t, i + 1, len(times))) # idCaseStudy = f"{id}" idCaseStudy = f"{id}_{caseStudy}" folderTimeMean = os.path.join(folder.outputs, idCaseStudy, "time_{}".format(times[i]), "profilesMean", indicator) folderTimeVariances = os.path.join(folder.outputs, idCaseStudy, "time_{}".format(times[i]), "profilesVariances", indicator) folderTimeFluxes = os.path.join(folder.outputs, idCaseStudy, "time_{}".format(times[i]), "profilesFluxes", indicator) if os.path.isdir(folderTimeMean): dataAll["times"].append(t) data = {} for variable in variables: dataMean = loadProfiles(f"z_{variable}.mat", folderTimeMean) dataVariances = loadProfiles(f"z_{variable}{variable}.mat", folderTimeVariances) dataFluxes = loadProfiles(f"z_w{variable}.mat", folderTimeFluxes) # Small correction to the key naming convention key1 = f"{variable}1" key2 = f"{variable}2" key1New = f"{variable}_1" key2New = f"{variable}_2" for key in list(dataMean.keys()): if key1 in key: dataMean[key.replace(key1, key1New)] = dataMean.pop(key) if key2 in key: dataMean[key.replace(key2, key2New)] = dataMean.pop(key) # print(f"Replaced {key} with {key.replace(key2, key2New)}") data = {**data, **dataMean, **dataVariances, **dataFluxes} # Additional diagnostics data["e_res1"] = 0.5 * (data["uu_res1"] + data["vv_res1"] + data["ww_res1"]) data["e_res2"] = 0.5 * (data["uu_res2"] + data["vv_res2"] + data["ww_res2"]) data["e_sg1"] = 0.5 * (data["uu_sg1"] + data["vv_sg1"] + data["ww_sg1"]) data["e_sg2"] = 0.5 * (data["uu_sg2"] + data["vv_sg2"] + data["ww_sg2"]) data["e_1"] = data["e_res1"] + data["e_sg1"] data["e_2"] = data["e_res2"] + data["e_sg2"] data["e_res"] = data["sigma_1"] * data["e_res1"] + data[ "sigma_2"] * data["e_res2"] data["e_sg"] = data["sigma_1"] * data["e_sg1"] + data[ "sigma_2"] * data["e_sg2"] data["e"] = data["e_res"] + data["e_sg"] # Add data for profile in data.keys(): if "__" not in profile: # Remove any ridiculous values from data set data[profile][np.abs(data[profile]) > 1e10] = np.nan profile_name = profile # profile_name = f"LES_{profile}" if profile_name not in dataAll: dataAll[profile_name] = data[profile][0].reshape( (len(data[profile][0]), 1)) # if profile != "z": # dataAll[profile_name] *= 0 elif profile != "z": # elif profile != "LES_z": dataAll[profile_name] = np.concatenate( (dataAll[profile_name], data[profile][0].reshape( (len(data[profile][0]), 1))), axis=-1) if cloudData: print("Adding cloud timeseries as well") folderCloud = os.path.join(folder.outputs, idCaseStudy, "cloudContour") dataCloud = loadProfiles("cloud_fraction.mat", folder=folderCloud) for profile in dataCloud.keys(): if "__" not in profile: profile_name = profile # profile_name = f"LES_{profile}" if profile_name not in dataAll: dataAll[profile_name] = dataCloud[profile] print("Data preparation complete for variables: {}".format( list(dataAll.keys()))) folderOutput = os.path.join(folder.outputs, idCaseStudy, indicator) if not os.path.isdir(folderOutput): os.makedirs(folderOutput) savemat(os.path.join(folderOutput, "profiles.mat"), dataAll)
def main(): # Fetch folders for code structure folder = folders( folderScripts=os.path.dirname(os.path.realpath(__file__)), folderData="/mnt/f/Desktop/LES_Data" ) # Spacial and temporal discretisation dt = np.linspace(0.,2.,21) dt = np.linspace(0.,2.,51) xf = np.linspace(0.,1.,21)[:-1] xc = xf + (xf[1]-xf[0])/2. # Choose whether to have co-located grid (A-grid) or staggered grid (C-grid) velocity_face = False # Set resolution of parameter space to sample. # Note that processing time scales as resolution^3 resolution = 50 resolution = 11 eta1_arr = np.linspace(0.01,2.,resolution) u1_arr = np.linspace(0.,2.,resolution) S10_arr = np.linspace(0.,1.,resolution) eta1_arr = np.linspace(1e-8,2.,resolution) u1_arr = np.linspace(-150.,150.,resolution) S10_arr = np.linspace(0.,1.,resolution) # S10_arr = np.array([1.]) # Placeholder arrays which will be multiplied by a factor later on eta0 = np.ones(len(xc)) eta1 = np.ones(len(xc)) theta0 = 300.*np.ones(len(xc)) theta1 = 301.*np.ones(len(xc)) u0 = np.ones(len(xf)) u1 = np.ones(len(xf)) S01 = np.ones(len(xc)) S10 = np.ones(len(xc)) # Make transfers like a square wave to test stability at steep gradients # Only necessary for staggered grids. for j in xrange(len(S01)): if xc[j] < 0.2 or xc[j] > 0.8: S01[j] = 0. S10[j] = 0. # Allowed numerical schemes # test_cases = [["flux","n","n",0,0],["flux","n+1","n+1",1,1]] test_cases = [["advective","n","n",0,1],["advective","n","n+1",0,0],["advective","n+1","n",1,1],["advective","n+1","n+1",1,0]] delta_ke_list = [] for test_case in test_cases: momentum_eq = test_case[0] q = test_case[1] r = test_case[2] delta_ke_min = 1e+16*np.ones((2,2,len(dt))) delta_ke_max = -1e+16*np.ones((2,2,len(dt))) delta_ke_mean = np.zeros((2,2,len(dt))) delta_f_min = 1e+16*np.ones((2,2,len(dt))) delta_f_max = -1e+16*np.ones((2,2,len(dt))) delta_f_mean = np.zeros((2,2,len(dt))) # Try different timesteps. Explicit schemes tend to become unstable for large dt. for n in xrange(len(dt)): print dt[n] # Cycle over all parameter space for ie in eta1_arr: for iu in u1_arr: for iS in S10_arr: # eta = [(1-eta1_arr[ie])*eta0.copy(), eta1_arr[ie]*eta1.copy()] eta = [eta0.copy(), ie*eta1.copy()] theta = [theta0.copy(), theta1.copy()] u = [u0.copy(),iu*u1.copy()] S = [[0*S01,S01],[iS*S10,0*S10]] # Canculate energy, momentum and velocity changes delta_ke_00,delta_f_00,u_new_00 = deltaE(eta, theta, u, dt[n], S, 0, 0, 0, q, r, velocity_face=velocity_face, momentum_eq=momentum_eq) delta_ke_01,delta_f_01,u_new_01 = deltaE(eta, theta, u, dt[n], S, 0, 1, 1, q, r, velocity_face=velocity_face, momentum_eq=momentum_eq) delta_ke_10,delta_f_10,u_new_10 = deltaE(eta, theta, u, dt[n], S, 1, 0, 0, q, r, velocity_face=velocity_face, momentum_eq=momentum_eq) delta_ke_11,delta_f_11,u_new_11 = deltaE(eta, theta, u, dt[n], S, 1, 1, 1, q, r, velocity_face=velocity_face, momentum_eq=momentum_eq) # Update maximum recorded maxima and minima delta_ke_min[0][0][n] = min(delta_ke_min[0][0][n], np.min(delta_ke_00)) delta_ke_max[0][0][n] = max(delta_ke_max[0][0][n], np.max(delta_ke_00)) delta_ke_mean[0][0][n] += np.mean(delta_ke_00)/(1.*resolution**3) delta_ke_min[0][1][n] = min(delta_ke_min[0][1][n], np.min(delta_ke_01)) delta_ke_max[0][1][n] = max(delta_ke_max[0][1][n], np.max(delta_ke_01)) delta_ke_mean[0][1][n] += np.mean(delta_ke_01)/(1.*resolution**3) delta_ke_min[1][0][n] = min(delta_ke_min[1][0][n], np.min(delta_ke_10)) delta_ke_max[1][0][n] = max(delta_ke_max[1][0][n], np.max(delta_ke_10)) delta_ke_mean[1][0][n] += np.mean(delta_ke_10)/(1.*resolution**3) delta_ke_min[1][1][n] = min(delta_ke_min[1][1][n], np.min(delta_ke_11)) delta_ke_max[1][1][n] = max(delta_ke_max[1][1][n], np.max(delta_ke_11)) delta_ke_mean[1][1][n] += np.mean(delta_ke_11)/(1.*resolution**3) delta_f_min[0][0][n] = min(delta_f_min[0][0][n], np.min(delta_f_00)) delta_f_max[0][0][n] = max(delta_f_max[0][0][n], np.max(delta_f_00)) delta_f_mean[0][0][n] += np.mean(delta_f_00)/(1.*resolution**3) delta_f_min[0][1][n] = min(delta_f_min[0][1][n], np.min(delta_f_01)) delta_f_max[0][1][n] = max(delta_f_max[0][1][n], np.max(delta_f_01)) delta_f_mean[0][1][n] += np.mean(delta_f_01)/(1.*resolution**3) delta_f_min[1][0][n] = min(delta_f_min[1][0][n], np.min(delta_f_10)) delta_f_max[1][0][n] = max(delta_f_max[1][0][n], np.max(delta_f_10)) delta_f_mean[1][0][n] += np.mean(delta_f_10)/(1.*resolution**3) delta_f_min[1][1][n] = min(delta_f_min[1][1][n], np.min(delta_f_11)) delta_f_max[1][1][n] = max(delta_f_max[1][1][n], np.max(delta_f_11)) delta_f_mean[1][1][n] += np.mean(delta_f_11)/(1.*resolution**3) # Define colors and linestyles necessary to distinguish between similar profiles colors = [["#7a7a7a","b"],["r","k"]] linestyles = ["-","--",":","-."] linestyles = ["-","-","-","-"] # plt.figure(figsize=(5,5)) plt.figure(figsize=(9,4)) spread = np.zeros((4)) for i in xrange(2): for j in xrange(2): spread[2*i+j] = np.max(delta_ke_max[i][j]-delta_ke_min[i][j]) spread_index = spread.argsort()[::-1] # Fill region between maximum and minimum regions for n in spread_index: j = n%2 i = (n-j)/2 delta_ke_min[i][j] = delta_ke_min[i][j].clip(min=-1e2) delta_ke_max[i][j] = delta_ke_max[i][j].clip(max= 1e2) for k in xrange(len(delta_ke_min[i][j])): if delta_ke_min[i][j][k] < 1e-13 and delta_ke_min[i][j][k] > -1e-13: delta_ke_min[i][j][k] = 0. if delta_ke_max[i][j][k] < 1e-13 and delta_ke_max[i][j][k] > -1e-13: delta_ke_max[i][j][k] = 0. y1 = delta_ke_min[i][j] y2 = delta_ke_max[i][j] if i == j: plt.fill_between(dt, y1, y2, where= y2 >= y1, facecolor=colors[i][j], interpolate=True, linewidth=0., alpha = 0.5) for n in xrange(len(spread_index)): j = spread_index[n]%2 i = (spread_index[n]-j)/2 # If maximum value is 0 (to numerical precision), indicate the energy-diminishing properties linewidth = 3. linestyle = "--" if np.max(delta_ke_max[i][j]) < 1e-13: linestyle = "-" if i == j: plt.plot(dt,delta_ke_min[i][j],color=colors[i][j], linestyle=linestyle, linewidth=linewidth) plt.plot(dt,delta_ke_max[i][j],color=colors[i][j], linestyle=linestyle, linewidth=linewidth) plt.plot(dt,0*dt,":",color="w") # Labels and formating plt.xlabel("$\\Delta t$ $S_{01}$",fontsize=20) plt.ylabel("Rel. Energy change, $\\Delta E_{REL}$",fontsize=20) plt.xlim(dt[0],dt[-1]) plt.ylim(-3.9999e-2,3.9999e-2) plt.xscale("sqrt2") plt.yscale("sqrt2") filename = "conservation_ke_{}_q_{}_r_{}.png".format(test_case[0],q.replace("+","p"),r.replace("+","p")) plt.savefig( os.path.join(folder.outputs, filename), bbox_inches='tight', dpi=200 ) plt.close() # Save profiles for final energy plot if q == "n" and r == "n": delta_ke_list.append( [delta_ke_min[0][1], delta_ke_max[0][1], "b"] ) if q == "n+1" and r == "n": delta_ke_list.append( [delta_ke_min[1][1], delta_ke_max[1][1], "k"] ) if q == "n" and r == "n+1": delta_ke_list.append( [delta_ke_min[0][0], delta_ke_max[0][0], "#7a7a7a"] ) if q == "n+1" and r == "n+1": delta_ke_list.append( [delta_ke_min[1][0], delta_ke_max[1][0], "r"] ) # plt.figure(figsize=(5,5)) plt.figure(figsize=(9,4)) spread = np.zeros((4)) for i in xrange(2): for j in xrange(2): spread[2*i+j] = np.max(delta_f_max[i][j]-delta_f_min[i][j]) spread_index = spread.argsort()[::-1] for n in spread_index: j = n%2 i = (n-j)/2 delta_f_min[i][j] = delta_f_min[i][j].clip(min=-1e2) delta_f_max[i][j] = delta_f_max[i][j].clip(max= 1e2) for k in xrange(len(delta_f_min[i][j])): if delta_f_min[i][j][k] < 1e-13 and delta_f_min[i][j][k] > -1e-13: delta_f_min[i][j][k] = 0. if delta_f_max[i][j][k] < 1e-13 and delta_f_max[i][j][k] > -1e-13: delta_f_max[i][j][k] = 0. y1 = delta_f_min[i][j] y2 = delta_f_max[i][j] plt.fill_between(dt, y1, y2, facecolor=colors[i][j], interpolate=True, alpha = 0.5, linewidth=0.) for n in xrange(len(spread_index)): j = spread_index[n]%2 i = (spread_index[n]-j)/2 linewidth = 3. if n == 0: linewidth = 4. # Indicate whether a scheme conserves momentum to numerical precision linestyle = "--" if np.max(delta_f_max[i][j]) <= 1e-2 and np.min(delta_f_min[i][j]) >= -1e-2: linestyle = "-" plt.plot(dt,delta_f_min[i][j],color=colors[i][j], linestyle=linestyle, linewidth=linewidth) plt.plot(dt,delta_f_max[i][j],color=colors[i][j], linestyle=linestyle, linewidth=linewidth) plt.plot(dt,0*dt,":",color="w") # Labels and formating plt.xlabel("$\\Delta t$ $S_{01}$",fontsize=20) plt.ylabel("Rel. mom. change, $\\Delta F_{REL}$",fontsize=20) plt.xlim(dt[0],dt[-1]) plt.ylim(-40.,40.) plt.xscale("sqrt2") plt.yscale("sqrt2") filename = "conservation_f_{}_q_{}_r_{}.png".format(test_case[0],q.replace("+","p"),r.replace("+","p")) plt.savefig( os.path.join(folder.outputs, filename), bbox_inches='tight', dpi=200 ) plt.close() # Plot energy profiles of hand-selected schemes plt.figure(figsize=(9,4)) for n in xrange(len(delta_ke_list)): y1 = delta_ke_list[n][0] y2 = delta_ke_list[n][1] plt.fill_between(dt, y1, y2, facecolor=delta_ke_list[n][2], interpolate=True, linewidth=0., alpha = 0.5) for n in xrange(len(delta_ke_list)): linestyle = "--" if np.max(delta_ke_list[n][1]) < 1e-13: linestyle = "-" plt.plot(dt,delta_ke_list[n][0],color=delta_ke_list[n][2], linestyle=linestyle, linewidth=3.) plt.plot(dt,delta_ke_list[n][1],color=delta_ke_list[n][2], linestyle=linestyle, linewidth=3.) plt.plot(dt,0*dt,":",color="w") plt.xlabel("$\\Delta t$ $S_{01}$",fontsize=20) plt.ylabel("Rel. Energy change, $\\Delta E_{REL}$",fontsize=20) plt.xlim(dt[0],dt[-1]) plt.ylim(-3.9999e-2,3.9999e-2) plt.xscale("sqrt2") plt.yscale("sqrt2") plt.savefig(os.path.join(folder.outputs, "conservation_ke.png") , bbox_inches='tight', dpi=200) plt.close()
def main(): # Fetch folders for code structure folder = folders(folderScripts=os.path.dirname(os.path.realpath(__file__))) # Import the mesh for the fluid solver mesh = cubeMesh2D(xPeriodic=True) x = mesh.x z = mesh.z # Import finite volume operations using mesh geometry fvc = finiteVolumeFunctions(mesh) # Initialise the simulation simulation = runSettings( dt=0.01, # Timestep for simulation tEnd=1000, # End time (s) of simulation plotInterval=10. # Plot every [plotInterval] seconds ) # Constants T = 300 R = 8.31 g = mesh.volVectorField.copy() # g[:,:,1] = -9.81 ''' INITIAL CONDITIONS ''' # Velocity field u = mesh.volVectorField.copy() u += 10. u[:49, :] = -10. u[:51, 50:150] = -10. # Density field rho = 0 * mesh.volScalarField.copy() + 1 tracer = mesh.volScalarField.copy() tracer += 0.999 tracer[:49, :] = 0.001 tracer[:51, 50:150] = 0.001 dt = simulation.dt # Plot initial conditions plotContour(x, z, tracer, "kelvinHelmholtz_0.png", folder=folder.outputs) # Run simulation until end time is reached while simulation.updateTime(): sys.stdout.write("\rRunning simulation, t={}s".format( simulation.currentTime)) sys.stdout.flush() pressure = rho * R * T # Continuity equation rho = rho - dt * fvc.div(rho, u, "upwind") rho = fvc.setBoundaryConditions(rho) # Momentum equation u = u - dt * fvc.uDotGradU(u, "upwind") + dt * g - dt * fvc.grad( pressure, "linear") / rho[:, :, None] u = fvc.setBoundaryConditions(u) # Advection of tracers which follow the flow tracer = tracer - dt * dot(u, fvc.grad(tracer, "upwind", u=u)) if simulation.plotFigures(): print "\nPlotting profiles at t={}s".format(simulation.currentTime) fileId = "kelvinHelmholtz_{}.png".format( simulation.currentTimeIndex) plotContour(x, z, tracer, fileId, folder=folder.outputs)
def plotFields(id="default"): ''' Generate plots for the acceleration and radiation profiles for a neutral atom in a Magneto-Optical Trap with one laser pointed down on a horizontal surface where a reflection grating is located. NOTE: plotContour must be run before using plotFields Args id: Data id used for the input data filename and the output files ''' print(f"\nPlotting fields for configuration: {id}") folder = folders(id=id, folderScripts=os.path.dirname(os.path.realpath(__file__))) # Save fields for future use data = np.load(os.path.join(folder.outputs, "fieldData.npz")) slices = {} slices["XZ"] = { "xAxis": "x", "yAxis": "z", "xIndex": 0, "yIndex": 2, "location": "y = {:.2f} cm".format(data["axisY"][int(data["resolution"] / 2)]), "slice": np.s_[:, int(data["resolution"] / 2), :] } slices["YZ"] = { "xAxis": "y", "yAxis": "z", "xIndex": 1, "yIndex": 2, "location": "x = {:.2f} cm".format(data["axisX"][int(data["resolution"] / 2)]), "slice": np.s_[:, :, int(data["resolution"] / 2)] } slices["XY"] = { "xAxis": "x", "yAxis": "y", "xIndex": 0, "yIndex": 1, "location": "z = {:.2f} cm".format(data["axisZ"][int(data["resolution"] / 2)]), "slice": np.s_[int(data["resolution"] / 2), :, :] } for slice in slices: print("Plotting data for slice {}".format(slice)) s = slices[slice] plotContour(data["axis" + s["xAxis"].upper()], data["axis" + s["yAxis"].upper()], data["radPressureMag"][s["slice"]], id=id + "_radPressure_" + slice.lower(), folder=folder.outputs, xlabel="{} (cm)".format(s["xAxis"]), ylabel="{} (cm)".format(s["yAxis"]), ylabelCBar="Relative radiation pressure", title="Radiation pressure field, {}".format(s["location"]), u=data["radPressure"][s["slice"]][..., s["xIndex"]], v=data["radPressure"][s["slice"]][..., s["yIndex"]], vectorScale=10) plotContour(data["axis" + s["xAxis"].upper()], data["axis" + s["yAxis"].upper()], data["aMag"][s["slice"]], id=id + "_a_" + slice.lower(), folder=folder.outputs, cmap="jet_r", xlabel="{} (cm)".format(s["xAxis"]), ylabel="{} (cm)".format(s["yAxis"]), ylabelCBar="Relative acceleration", title="Acceleration field, {}".format(s["location"]), u=data["a"][s["slice"]][..., s["xIndex"]], v=data["a"][s["slice"]][..., s["yIndex"]], vectorScale=2e5)
def main(): # Fetch folders for code structure folder = folders(folderScripts=os.path.dirname(os.path.realpath(__file__)), folderData="/mnt/f/Desktop/LES_Data") # Get Large Eddy Simulation data and Single Column Model data les = getLesData(os.path.join(folder.data, "mov0235_ALL_01-_.nc")) scm = getScmData(os.path.join(folder.data, "SCM_results.mat")) # Create plots for each snapshot in time for n in range(len(les.t)): folderTime = os.path.join(folder.outputs, "timestep_{}".format(n)) if not os.path.isdir(folderTime): os.makedirs(folderTime) snapshot = les.data[n] # Create plots for each layer in the vertical for k in range(len(snapshot.z)): layer = snapshot.z[k] * 1e-3 title = "z = {:.2f}km (id={})".format(layer, k + 1) print "Layer {} ({:.3f}km)".format(k + 1, layer) scmGaussian = {} scmGaussian["sigma1"] = interpolateFromArray( scm["SCM_zw"][0], snapshot.z[k], scm["SCM_sigma1w"][:, 2]) scmGaussian["sigma2"] = interpolateFromArray( scm["SCM_zw"][0], snapshot.z[k], scm["SCM_sigma2w"][:, 2]) scmGaussian["w1"] = interpolateFromArray(scm["SCM_zw"][0], snapshot.z[k], scm["SCM_w_1"][:, 2]) scmGaussian["w2"] = interpolateFromArray(scm["SCM_zw"][0], snapshot.z[k], scm["SCM_w_2"][:, 2]) scmGaussian["wVar1"] = interpolateFromArray( scm["SCM_zw"][0], snapshot.z[k], scm["SCM_ww1"][:, 2]) scmGaussian["wVar2"] = interpolateFromArray( scm["SCM_zw"][0], snapshot.z[k], scm["SCM_ww2"][:, 2]) # Histogram for vertical velocity, w plotHistogramWithGaussian(snapshot.w, snapshot.I2, layer, k, title=title, folder=os.path.join( folderTime, snapshot.w.name), scmGaussian=scmGaussian) # Histogram for water vapour, qv # plotHistogramWithGaussian( # snapshot.qv, # snapshot.I2, # layer, # k, # title=title, # folder=os.path.join(folderTime, snapshot.qv.name) # ) # Histogram for liquid water, ql # plotHistogramWithGaussian( # snapshot.ql, # snapshot.I2, # layer, # k, # title=title, # folder=os.path.join(folderTime, snapshot.ql.name) # ) # Remove les data to clear memory totalTimesteps = len(les.t) totalImages = min(len(snapshot.z), 150) del les del snapshot